diff options
author | chriseth <c@ethdev.com> | 2016-12-15 19:16:32 +0800 |
---|---|---|
committer | chriseth <c@ethdev.com> | 2016-12-15 19:16:56 +0800 |
commit | 822622cf5bf23e79a6e2292cb837d1a39ca1c419 (patch) | |
tree | e668cf9a257bab10e77469ba725e630bc8f3b0a5 /test/libsolidity | |
parent | 2dabbdf06f414750ef0425c664f861aeb3e470b8 (diff) | |
parent | 3a692e3df9b62852c951adece42f6d12b2d4a44a (diff) | |
download | dexon-solidity-822622cf5bf23e79a6e2292cb837d1a39ca1c419.tar.gz dexon-solidity-822622cf5bf23e79a6e2292cb837d1a39ca1c419.tar.zst dexon-solidity-822622cf5bf23e79a6e2292cb837d1a39ca1c419.zip |
Merge remote-tracking branch 'origin/develop' into release
Diffstat (limited to 'test/libsolidity')
-rw-r--r-- | test/libsolidity/ASTJSON.cpp | 8 | ||||
-rw-r--r-- | test/libsolidity/Assembly.cpp | 12 | ||||
-rw-r--r-- | test/libsolidity/ErrorCheck.cpp | 34 | ||||
-rw-r--r-- | test/libsolidity/ErrorCheck.h | 32 | ||||
-rw-r--r-- | test/libsolidity/GasMeter.cpp | 11 | ||||
-rw-r--r-- | test/libsolidity/Imports.cpp | 8 | ||||
-rw-r--r-- | test/libsolidity/InlineAssembly.cpp | 8 | ||||
-rw-r--r-- | test/libsolidity/SemVerMatcher.cpp | 8 | ||||
-rw-r--r-- | test/libsolidity/SolidityABIJSON.cpp | 149 | ||||
-rw-r--r-- | test/libsolidity/SolidityEndToEndTest.cpp | 1709 | ||||
-rw-r--r-- | test/libsolidity/SolidityExecutionFramework.cpp | 116 | ||||
-rw-r--r-- | test/libsolidity/SolidityExecutionFramework.h | 255 | ||||
-rw-r--r-- | test/libsolidity/SolidityExpressionCompiler.cpp | 134 | ||||
-rw-r--r-- | test/libsolidity/SolidityNameAndTypeResolution.cpp | 1713 | ||||
-rw-r--r-- | test/libsolidity/SolidityNatspecJSON.cpp | 352 | ||||
-rw-r--r-- | test/libsolidity/SolidityOptimizer.cpp | 149 | ||||
-rw-r--r-- | test/libsolidity/SolidityParser.cpp | 742 | ||||
-rw-r--r-- | test/libsolidity/SolidityScanner.cpp | 8 | ||||
-rw-r--r-- | test/libsolidity/SolidityTypes.cpp | 8 |
19 files changed, 3261 insertions, 2195 deletions
diff --git a/test/libsolidity/ASTJSON.cpp b/test/libsolidity/ASTJSON.cpp index b88218e7..0972ce82 100644 --- a/test/libsolidity/ASTJSON.cpp +++ b/test/libsolidity/ASTJSON.cpp @@ -1,18 +1,18 @@ /* - This file is part of cpp-ethereum. + This file is part of solidity. - cpp-ethereum is free software: you can redistribute it and/or modify + 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. - cpp-ethereum is distributed in the hope that it will be useful, + 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. + along with solidity. If not, see <http://www.gnu.org/licenses/>. */ /** * @author Christian <c@ethdev.com> diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index e5ce691b..155dd5c9 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -1,18 +1,18 @@ /* - This file is part of cpp-ethereum. + This file is part of solidity. - cpp-ethereum is free software: you can redistribute it and/or modify + 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. - cpp-ethereum is distributed in the hope that it will be useful, + 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. + along with solidity. If not, see <http://www.gnu.org/licenses/>. */ /** * @author Lefteris Karapetsas <lefteris@ethdev.com> @@ -75,7 +75,7 @@ eth::AssemblyItems compileContract(const string& _sourceCode) if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get())) { Compiler compiler; - compiler.compileContract(*contract, map<ContractDefinition const*, Assembly const*>{}); + compiler.compileContract(*contract, map<ContractDefinition const*, Assembly const*>{}, bytes()); return compiler.runtimeAssemblyItems(); } @@ -116,7 +116,7 @@ BOOST_AUTO_TEST_CASE(location_test) shared_ptr<string const> n = make_shared<string>(""); AssemblyItems items = compileContract(sourceCode); vector<SourceLocation> locations = - vector<SourceLocation>(16, SourceLocation(2, 75, n)) + + vector<SourceLocation>(18, SourceLocation(2, 75, n)) + vector<SourceLocation>(27, SourceLocation(20, 72, n)) + vector<SourceLocation>{SourceLocation(42, 51, n), SourceLocation(65, 67, n)} + vector<SourceLocation>(2, SourceLocation(58, 67, n)) + diff --git a/test/libsolidity/ErrorCheck.cpp b/test/libsolidity/ErrorCheck.cpp new file mode 100644 index 00000000..75555c9b --- /dev/null +++ b/test/libsolidity/ErrorCheck.cpp @@ -0,0 +1,34 @@ +/* + 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/>. +*/ +/** @file ErrorCheck.cpp + * @author Yoichi Hirai <i@yoichihirai.com> + * @date 2016 + */ + +#include <test/libsolidity/ErrorCheck.h> +#include <libdevcore/Exceptions.h> + +#include <string> + +using namespace std; + +bool dev::solidity::searchErrorMessage(Error const& _err, std::string const& _substr) +{ + if (string const* errorMessage = boost::get_error_info<dev::errinfo_comment>(_err)) + return errorMessage->find(_substr) != std::string::npos; + return _substr.empty(); +} diff --git a/test/libsolidity/ErrorCheck.h b/test/libsolidity/ErrorCheck.h new file mode 100644 index 00000000..a309a9d3 --- /dev/null +++ b/test/libsolidity/ErrorCheck.h @@ -0,0 +1,32 @@ +/* + 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/>. +*/ +/** @file ErrorCheck.h + * @author Yoichi Hirai <i@yoichihirai.com> + * @date 2016 + */ + +#pragma once + +#include <libsolidity/interface/Exceptions.h> + +namespace dev +{ +namespace solidity +{ +bool searchErrorMessage(Error const& _err, std::string const& _substr); +} +} diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp index fc103393..0671fb15 100644 --- a/test/libsolidity/GasMeter.cpp +++ b/test/libsolidity/GasMeter.cpp @@ -1,18 +1,18 @@ /* - This file is part of cpp-ethereum. + This file is part of solidity. - cpp-ethereum is free software: you can redistribute it and/or modify + 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. - cpp-ethereum is distributed in the hope that it will be useful, + 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. + along with solidity. If not, see <http://www.gnu.org/licenses/>. */ /** * @author Christian <c@ethdev.com> @@ -32,6 +32,7 @@ using namespace std; using namespace dev::eth; using namespace dev::solidity; +using namespace dev::test; namespace dev { @@ -40,7 +41,7 @@ namespace solidity namespace test { -class GasMeterTestFramework: public ExecutionFramework +class GasMeterTestFramework: public SolidityExecutionFramework { public: GasMeterTestFramework() { } diff --git a/test/libsolidity/Imports.cpp b/test/libsolidity/Imports.cpp index 1a9e16cc..bc6adc26 100644 --- a/test/libsolidity/Imports.cpp +++ b/test/libsolidity/Imports.cpp @@ -1,18 +1,18 @@ /* - This file is part of cpp-ethereum. + This file is part of solidity. - cpp-ethereum is free software: you can redistribute it and/or modify + 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. - cpp-ethereum is distributed in the hope that it will be useful, + 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. + along with solidity. If not, see <http://www.gnu.org/licenses/>. */ /** * @author Christian <c@ethdev.com> diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp index 185a6215..64073edc 100644 --- a/test/libsolidity/InlineAssembly.cpp +++ b/test/libsolidity/InlineAssembly.cpp @@ -1,18 +1,18 @@ /* - This file is part of cpp-ethereum. + This file is part of solidity. - cpp-ethereum is free software: you can redistribute it and/or modify + 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. - cpp-ethereum is distributed in the hope that it will be useful, + 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. + along with solidity. If not, see <http://www.gnu.org/licenses/>. */ /** * @author Christian <c@ethdev.com> diff --git a/test/libsolidity/SemVerMatcher.cpp b/test/libsolidity/SemVerMatcher.cpp index 80bdf16f..08ef5277 100644 --- a/test/libsolidity/SemVerMatcher.cpp +++ b/test/libsolidity/SemVerMatcher.cpp @@ -1,18 +1,18 @@ /* - This file is part of cpp-ethereum. + This file is part of solidity. - cpp-ethereum is free software: you can redistribute it and/or modify + 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. - cpp-ethereum is distributed in the hope that it will be useful, + 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. + along with solidity. If not, see <http://www.gnu.org/licenses/>. */ /** * @author Christian <chris@ethereum.org> diff --git a/test/libsolidity/SolidityABIJSON.cpp b/test/libsolidity/SolidityABIJSON.cpp index a8a39b0b..043d74ed 100644 --- a/test/libsolidity/SolidityABIJSON.cpp +++ b/test/libsolidity/SolidityABIJSON.cpp @@ -1,18 +1,18 @@ /* - This file is part of cpp-ethereum. + This file is part of solidity. - cpp-ethereum is free software: you can redistribute it and/or modify + 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. - cpp-ethereum is distributed in the hope that it will be useful, + 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. + along with solidity. If not, see <http://www.gnu.org/licenses/>. */ /** * @author Marek Kotewicz <marek@ethdev.com> @@ -22,8 +22,11 @@ #include "../TestHelper.h" #include <libsolidity/interface/CompilerStack.h> -#include <json/json.h> + #include <libdevcore/Exceptions.h> +#include <libdevcore/SwarmHash.h> + +#include <json/json.h> namespace dev { @@ -51,7 +54,7 @@ public: ); } -private: +protected: CompilerStack m_compilerStack; Json::Reader m_reader; }; @@ -60,9 +63,11 @@ BOOST_FIXTURE_TEST_SUITE(SolidityABIJSON, JSONInterfaceChecker) BOOST_AUTO_TEST_CASE(basic_test) { - char const* sourceCode = "contract test {\n" - " function f(uint a) returns(uint d) { return a * 7; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint a) returns(uint d) { return a * 7; } + } + )"; char const* interface = R"([ { @@ -90,8 +95,9 @@ BOOST_AUTO_TEST_CASE(basic_test) BOOST_AUTO_TEST_CASE(empty_contract) { - char const* sourceCode = "contract test {\n" - "}\n"; + char const* sourceCode = R"( + contract test { } + )"; char const* interface = "[]"; checkInterface(sourceCode, interface); @@ -99,10 +105,12 @@ BOOST_AUTO_TEST_CASE(empty_contract) BOOST_AUTO_TEST_CASE(multiple_methods) { - char const* sourceCode = "contract test {\n" - " function f(uint a) returns(uint d) { return a * 7; }\n" - " function g(uint b) returns(uint e) { return b * 8; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint a) returns(uint d) { return a * 7; } + function g(uint b) returns(uint e) { return b * 8; } + } + )"; char const* interface = R"([ { @@ -148,9 +156,11 @@ BOOST_AUTO_TEST_CASE(multiple_methods) BOOST_AUTO_TEST_CASE(multiple_params) { - char const* sourceCode = "contract test {\n" - " function f(uint a, uint b) returns(uint d) { return a + b; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint a, uint b) returns(uint d) { return a + b; } + } + )"; char const* interface = R"([ { @@ -183,10 +193,12 @@ BOOST_AUTO_TEST_CASE(multiple_params) BOOST_AUTO_TEST_CASE(multiple_methods_order) { // methods are expected to be in alpabetical order - char const* sourceCode = "contract test {\n" - " function f(uint a) returns(uint d) { return a * 7; }\n" - " function c(uint b) returns(uint e) { return b * 8; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint a) returns(uint d) { return a * 7; } + function c(uint b) returns(uint e) { return b * 8; } + } + )"; char const* interface = R"([ { @@ -232,10 +244,12 @@ BOOST_AUTO_TEST_CASE(multiple_methods_order) BOOST_AUTO_TEST_CASE(const_function) { - char const* sourceCode = "contract test {\n" - " function foo(uint a, uint b) returns(uint d) { return a + b; }\n" - " function boo(uint32 a) constant returns(uint b) { return a * 4; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function foo(uint a, uint b) returns(uint d) { return a + b; } + function boo(uint32 a) constant returns(uint b) { return a * 4; } + } + )"; char const* interface = R"([ { @@ -283,11 +297,13 @@ BOOST_AUTO_TEST_CASE(const_function) BOOST_AUTO_TEST_CASE(events) { - char const* sourceCode = "contract test {\n" - " function f(uint a) returns(uint d) { return a * 7; }\n" - " event e1(uint b, address indexed c); \n" - " event e2(); \n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint a) returns(uint d) { return a * 7; } + event e1(uint b, address indexed c); + event e2(); + } + )"; char const* interface = R"([ { "name": "f", @@ -338,9 +354,11 @@ BOOST_AUTO_TEST_CASE(events) BOOST_AUTO_TEST_CASE(events_anonymous) { - char const* sourceCode = "contract test {\n" - " event e() anonymous; \n" - "}\n"; + char const* sourceCode = R"( + contract test { + event e() anonymous; + } + )"; char const* interface = R"([ { "name": "e", @@ -356,15 +374,16 @@ BOOST_AUTO_TEST_CASE(events_anonymous) BOOST_AUTO_TEST_CASE(inherited) { - char const* sourceCode = - " contract Base { \n" - " function baseFunction(uint p) returns (uint i) { return p; } \n" - " event baseEvent(bytes32 indexed evtArgBase); \n" - " } \n" - " contract Derived is Base { \n" - " function derivedFunction(bytes32 p) returns (bytes32 i) { return p; } \n" - " event derivedEvent(uint indexed evtArgDerived); \n" - " }"; + char const* sourceCode = R"( + contract Base { + function baseFunction(uint p) returns (uint i) { return p; } + event baseEvent(bytes32 indexed evtArgBase); + } + contract Derived is Base { + function derivedFunction(bytes32 p) returns (bytes32 i) { return p; } + event derivedEvent(uint indexed evtArgDerived); + } + )"; char const* interface = R"([ { @@ -428,13 +447,14 @@ BOOST_AUTO_TEST_CASE(inherited) BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one) { char const* sourceCode = R"( - contract test { - function f(uint, uint k) returns(uint ret_k, uint ret_g){ - uint g = 8; - ret_k = k; - ret_g = g; + contract test { + function f(uint, uint k) returns(uint ret_k, uint ret_g) { + uint g = 8; + ret_k = k; + ret_g = g; + } } - })"; + )"; char const* interface = R"([ { @@ -472,10 +492,11 @@ BOOST_AUTO_TEST_CASE(empty_name_return_parameter) { char const* sourceCode = R"( contract test { - function f(uint k) returns(uint){ - return k; + function f(uint k) returns(uint) { + return k; + } } - })"; + )"; char const* interface = R"([ { @@ -539,7 +560,7 @@ BOOST_AUTO_TEST_CASE(return_param_in_abi) contract test { enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } function test(ActionChoices param) {} - function ret() returns(ActionChoices){ + function ret() returns(ActionChoices) { ActionChoices action = ActionChoices.GoLeft; return action; } @@ -609,7 +630,7 @@ BOOST_AUTO_TEST_CASE(library_function) char const* sourceCode = R"( library test { struct StructType { uint a; } - function f(StructType storage b, uint[] storage c, test d) returns (uint[] e, StructType storage f){} + function f(StructType storage b, uint[] storage c, test d) returns (uint[] e, StructType storage f) {} } )"; @@ -731,6 +752,26 @@ BOOST_AUTO_TEST_CASE(function_type) checkInterface(sourceCode, interface); } +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; + contract test { + function g(function(uint) external returns (uint) x) {} + } + )"; + BOOST_REQUIRE(m_compilerStack.compile(std::string(sourceCode))); + bytes const& bytecode = m_compilerStack.runtimeObject("test").bytecode; + bytes hash = dev::swarmHash(m_compilerStack.onChainMetadata("test")).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{0xa1, 0x65, 'b', 'z', 'z', 'r', '0', 0x58, 0x20} + hash; + BOOST_CHECK(std::equal(expectation.begin(), expectation.end(), bytecode.end() - metadataCBORSize - 2)); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 4abe0894..94d4fb7f 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -1,18 +1,18 @@ /* - This file is part of cpp-ethereum. + This file is part of solidity. - cpp-ethereum is free software: you can redistribute it and/or modify + 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. - cpp-ethereum is distributed in the hope that it will be useful, + 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. + along with solidity. If not, see <http://www.gnu.org/licenses/>. */ /** * @author Christian <c@ethdev.com> @@ -25,11 +25,13 @@ #include <string> #include <tuple> #include <boost/test/unit_test.hpp> +#include <libevmasm/Assembly.h> #include <libsolidity/interface/Exceptions.h> #include <test/libsolidity/SolidityExecutionFramework.h> using namespace std; using namespace std::placeholders; +using namespace dev::test; namespace dev { @@ -38,21 +40,24 @@ namespace solidity namespace test { -BOOST_FIXTURE_TEST_SUITE(SolidityEndToEndTest, ExecutionFramework) +BOOST_FIXTURE_TEST_SUITE(SolidityEndToEndTest, SolidityExecutionFramework) BOOST_AUTO_TEST_CASE(smoke_test) { - char const* sourceCode = "contract test {\n" - " function f(uint a) returns(uint d) { return a * 7; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint a) returns(uint d) { return a * 7; } + } + )"; compileAndRun(sourceCode); - testSolidityAgainstCppOnRange("f(uint256)", [](u256 const& a) -> u256 { return a * 7; }, 0, 100); + testContractAgainstCppOnRange("f(uint256)", [](u256 const& a) -> u256 { return a * 7; }, 0, 100); } BOOST_AUTO_TEST_CASE(empty_contract) { - char const* sourceCode = "contract test {\n" - "}\n"; + char const* sourceCode = R"( + contract test { } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("i_am_not_there()", bytes()).empty()); } @@ -62,9 +67,10 @@ BOOST_AUTO_TEST_CASE(exp_operator) char const* sourceCode = R"( contract test { function f(uint a) returns(uint d) { return 2 ** a; } - })"; + } + )"; compileAndRun(sourceCode); - testSolidityAgainstCppOnRange("f(uint256)", [](u256 const& a) -> u256 { return u256(1 << a.convert_to<int>()); }, 0, 16); + testContractAgainstCppOnRange("f(uint256)", [](u256 const& a) -> u256 { return u256(1 << a.convert_to<int>()); }, 0, 16); } BOOST_AUTO_TEST_CASE(exp_operator_const) @@ -72,7 +78,8 @@ BOOST_AUTO_TEST_CASE(exp_operator_const) char const* sourceCode = R"( contract test { function f() returns(uint d) { return 2 ** 3; } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("f()", bytes()) == toBigEndian(u256(8))); } @@ -82,7 +89,8 @@ BOOST_AUTO_TEST_CASE(exp_operator_const_signed) char const* sourceCode = R"( contract test { function f() returns(int d) { return (-2) ** 3; } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("f()", bytes()) == toBigEndian(u256(-8))); } @@ -93,8 +101,9 @@ BOOST_AUTO_TEST_CASE(conditional_expression_true_literal) contract test { function f() returns(uint d) { return true ? 5 : 10; - } - })"; + } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("f()", bytes()) == toBigEndian(u256(5))); } @@ -105,8 +114,9 @@ BOOST_AUTO_TEST_CASE(conditional_expression_false_literal) contract test { function f() returns(uint d) { return false ? 5 : 10; - } - })"; + } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("f()", bytes()) == toBigEndian(u256(10))); } @@ -116,12 +126,13 @@ BOOST_AUTO_TEST_CASE(conditional_expression_multiple) char const* sourceCode = R"( contract test { function f(uint x) returns(uint d) { - return x > 100 ? + return x > 100 ? x > 1000 ? 1000 : 100 : x > 50 ? 50 : 10; - } - })"; + } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("f(uint256)", u256(1001)) == toBigEndian(u256(1000))); BOOST_CHECK(callContractFunction("f(uint256)", u256(500)) == toBigEndian(u256(100))); @@ -135,7 +146,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_return_values) contract test { function f(bool cond, uint v) returns (uint a, uint b) { cond ? a = v : b = v; - } + } })"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("f(bool,uint256)", true, u256(20)) == encodeArgs(u256(20), u256(0))); @@ -167,7 +178,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_storage_memory_1) } return ret; - } + } } )"; compileAndRun(sourceCode); @@ -201,7 +212,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_storage_memory_2) } return ret; - } + } } )"; compileAndRun(sourceCode); @@ -217,7 +228,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_different_types) uint8 x = 0xcd; uint16 y = 0xabab; return cond ? x : y; - } + } } )"; compileAndRun(sourceCode); @@ -275,12 +286,14 @@ BOOST_AUTO_TEST_CASE(conditional_expression_functions) BOOST_AUTO_TEST_CASE(recursive_calls) { - char const* sourceCode = "contract test {\n" - " function f(uint n) returns(uint nfac) {\n" - " if (n <= 1) return 1;\n" - " else return n * f(n - 1);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint n) returns(uint nfac) { + if (n <= 1) return 1; + else return n * f(n - 1); + } + } + )"; compileAndRun(sourceCode); function<u256(u256)> recursive_calls_cpp = [&recursive_calls_cpp](u256 const& n) -> u256 { @@ -290,17 +303,19 @@ BOOST_AUTO_TEST_CASE(recursive_calls) return n * recursive_calls_cpp(n - 1); }; - testSolidityAgainstCppOnRange("f(uint256)", recursive_calls_cpp, 0, 5); + testContractAgainstCppOnRange("f(uint256)", recursive_calls_cpp, 0, 5); } BOOST_AUTO_TEST_CASE(multiple_functions) { - char const* sourceCode = "contract test {\n" - " function a() returns(uint n) { return 0; }\n" - " function b() returns(uint n) { return 1; }\n" - " function c() returns(uint n) { return 2; }\n" - " function f() returns(uint n) { return 3; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a() returns(uint n) { return 0; } + function b() returns(uint n) { return 1; } + function c() returns(uint n) { return 2; } + function f() returns(uint n) { return 3; } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("a()", bytes()) == toBigEndian(u256(0))); BOOST_CHECK(callContractFunction("b()", bytes()) == toBigEndian(u256(1))); @@ -311,33 +326,39 @@ BOOST_AUTO_TEST_CASE(multiple_functions) BOOST_AUTO_TEST_CASE(named_args) { - char const* sourceCode = "contract test {\n" - " function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; }\n" - " function b() returns (uint r) { r = a({a: 1, b: 2, c: 3}); }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; } + function b() returns (uint r) { r = a({a: 1, b: 2, c: 3}); } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("b()", bytes()) == toBigEndian(u256(123))); } BOOST_AUTO_TEST_CASE(disorder_named_args) { - char const* sourceCode = "contract test {\n" - " function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; }\n" - " function b() returns (uint r) { r = a({c: 3, a: 1, b: 2}); }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; } + function b() returns (uint r) { r = a({c: 3, a: 1, b: 2}); } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("b()", bytes()) == toBigEndian(u256(123))); } BOOST_AUTO_TEST_CASE(while_loop) { - char const* sourceCode = "contract test {\n" - " function f(uint n) returns(uint nfac) {\n" - " nfac = 1;\n" - " var i = 2;\n" - " while (i <= n) nfac *= i++;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint n) returns(uint nfac) { + nfac = 1; + var i = 2; + while (i <= n) nfac *= i++; + } + } + )"; compileAndRun(sourceCode); auto while_loop_cpp = [](u256 const& n) -> u256 @@ -350,19 +371,21 @@ BOOST_AUTO_TEST_CASE(while_loop) return nfac; }; - testSolidityAgainstCppOnRange("f(uint256)", while_loop_cpp, 0, 5); + testContractAgainstCppOnRange("f(uint256)", while_loop_cpp, 0, 5); } BOOST_AUTO_TEST_CASE(do_while_loop) { - char const* sourceCode = "contract test {\n" - " function f(uint n) returns(uint nfac) {\n" - " nfac = 1;\n" - " var i = 2;\n" - " do { nfac *= i++; } while (i <= n);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint n) returns(uint nfac) { + nfac = 1; + var i = 2; + do { nfac *= i++; } while (i <= n); + } + } + )"; compileAndRun(sourceCode); auto do_while_loop_cpp = [](u256 const& n) -> u256 @@ -378,32 +401,34 @@ BOOST_AUTO_TEST_CASE(do_while_loop) return nfac; }; - testSolidityAgainstCppOnRange("f(uint256)", do_while_loop_cpp, 0, 5); + testContractAgainstCppOnRange("f(uint256)", do_while_loop_cpp, 0, 5); } BOOST_AUTO_TEST_CASE(nested_loops) { // tests that break and continue statements in nested loops jump to the correct place - char const* sourceCode = "contract test {\n" - " function f(uint x) returns(uint y) {\n" - " while (x > 1) {\n" - " if (x == 10) break;\n" - " while (x > 5) {\n" - " if (x == 8) break;\n" - " x--;\n" - " if (x == 6) continue;\n" - " return x;\n" - " }\n" - " x--;\n" - " if (x == 3) continue;\n" - " break;\n" - " }\n" - " return x;\n" - " }\n" - "}\n"; - compileAndRun(sourceCode); - - auto nested_loops_cpp = [](u256 n) -> u256 + char const* sourceCode = R"( + contract test { + function f(uint x) returns(uint y) { + while (x > 1) { + if (x == 10) break; + while (x > 5) { + if (x == 8) break; + x--; + if (x == 6) continue; + return x; + } + x--; + if (x == 3) continue; + break; + } + return x; + } + } + )"; + compileAndRun(sourceCode); + + auto nested_loops_cpp = [](u256 n) -> u256 { while (n > 1) { @@ -427,18 +452,20 @@ BOOST_AUTO_TEST_CASE(nested_loops) return n; }; - testSolidityAgainstCppOnRange("f(uint256)", nested_loops_cpp, 0, 12); + testContractAgainstCppOnRange("f(uint256)", nested_loops_cpp, 0, 12); } BOOST_AUTO_TEST_CASE(for_loop) { - char const* sourceCode = "contract test {\n" - " function f(uint n) returns(uint nfac) {\n" - " nfac = 1;\n" - " for (var i = 2; i <= n; i++)\n" - " nfac *= i;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint n) returns(uint nfac) { + nfac = 1; + for (var i = 2; i <= n; i++) + nfac *= i; + } + } + )"; compileAndRun(sourceCode); auto for_loop_cpp = [](u256 const& n) -> u256 @@ -449,21 +476,22 @@ BOOST_AUTO_TEST_CASE(for_loop) return nfac; }; - testSolidityAgainstCppOnRange("f(uint256)", for_loop_cpp, 0, 5); + testContractAgainstCppOnRange("f(uint256)", for_loop_cpp, 0, 5); } BOOST_AUTO_TEST_CASE(for_loop_empty) { - char const* sourceCode = "contract test {\n" - " function f() returns(uint ret) {\n" - " ret = 1;\n" - " for (;;)\n" - " {\n" - " ret += 1;\n" - " if (ret >= 10) break;\n" - " }\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f() returns(uint ret) { + ret = 1; + for (;;) { + ret += 1; + if (ret >= 10) break; + } + } + } + )"; compileAndRun(sourceCode); auto for_loop_empty_cpp = []() -> u256 @@ -477,19 +505,21 @@ BOOST_AUTO_TEST_CASE(for_loop_empty) return ret; }; - testSolidityAgainstCpp("f()", for_loop_empty_cpp); + testContractAgainstCpp("f()", for_loop_empty_cpp); } BOOST_AUTO_TEST_CASE(for_loop_simple_init_expr) { - char const* sourceCode = "contract test {\n" - " function f(uint n) returns(uint nfac) {\n" - " nfac = 1;\n" - " uint256 i;\n" - " for (i = 2; i <= n; i++)\n" - " nfac *= i;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint n) returns(uint nfac) { + nfac = 1; + uint256 i; + for (i = 2; i <= n; i++) + nfac *= i; + } + } + )"; compileAndRun(sourceCode); auto for_loop_simple_init_expr_cpp = [](u256 const& n) -> u256 @@ -501,7 +531,7 @@ BOOST_AUTO_TEST_CASE(for_loop_simple_init_expr) return nfac; }; - testSolidityAgainstCppOnRange("f(uint256)", for_loop_simple_init_expr_cpp, 0, 5); + testContractAgainstCppOnRange("f(uint256)", for_loop_simple_init_expr_cpp, 0, 5); } BOOST_AUTO_TEST_CASE(for_loop_break_continue) @@ -547,25 +577,27 @@ BOOST_AUTO_TEST_CASE(for_loop_break_continue) return i; }; - testSolidityAgainstCppOnRange("f(uint256)", breakContinue, 0, 10); + testContractAgainstCppOnRange("f(uint256)", breakContinue, 0, 10); } BOOST_AUTO_TEST_CASE(calling_other_functions) { - char const* sourceCode = "contract collatz {\n" - " function run(uint x) returns(uint y) {\n" - " while ((y = x) > 1) {\n" - " if (x % 2 == 0) x = evenStep(x);\n" - " else x = oddStep(x);\n" - " }\n" - " }\n" - " function evenStep(uint x) returns(uint y) {\n" - " return x / 2;\n" - " }\n" - " function oddStep(uint x) returns(uint y) {\n" - " return 3 * x + 1;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract collatz { + function run(uint x) returns(uint y) { + while ((y = x) > 1) { + if (x % 2 == 0) x = evenStep(x); + else x = oddStep(x); + } + } + function evenStep(uint x) returns(uint y) { + return x / 2; + } + function oddStep(uint x) returns(uint y) { + return 3 * x + 1; + } + } + )"; compileAndRun(sourceCode); auto evenStep_cpp = [](u256 const& n) -> u256 @@ -591,22 +623,24 @@ BOOST_AUTO_TEST_CASE(calling_other_functions) return y; }; - testSolidityAgainstCpp("run(uint256)", collatz_cpp, u256(0)); - testSolidityAgainstCpp("run(uint256)", collatz_cpp, u256(1)); - testSolidityAgainstCpp("run(uint256)", collatz_cpp, u256(2)); - testSolidityAgainstCpp("run(uint256)", collatz_cpp, u256(8)); - testSolidityAgainstCpp("run(uint256)", collatz_cpp, u256(127)); + testContractAgainstCpp("run(uint256)", collatz_cpp, u256(0)); + testContractAgainstCpp("run(uint256)", collatz_cpp, u256(1)); + testContractAgainstCpp("run(uint256)", collatz_cpp, u256(2)); + testContractAgainstCpp("run(uint256)", collatz_cpp, u256(8)); + testContractAgainstCpp("run(uint256)", collatz_cpp, u256(127)); } BOOST_AUTO_TEST_CASE(many_local_variables) { - char const* sourceCode = "contract test {\n" - " function run(uint x1, uint x2, uint x3) returns(uint y) {\n" - " var a = 0x1; var b = 0x10; var c = 0x100;\n" - " y = a + b + c + x1 + x2 + x3;\n" - " y += b + x2;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function run(uint x1, uint x2, uint x3) returns(uint y) { + var a = 0x1; var b = 0x10; var c = 0x100; + y = a + b + c + x1 + x2 + x3; + y += b + x2; + } + } + )"; compileAndRun(sourceCode); auto f = [](u256 const& x1, u256 const& x2, u256 const& x3) -> u256 { @@ -616,18 +650,20 @@ BOOST_AUTO_TEST_CASE(many_local_variables) u256 y = a + b + c + x1 + x2 + x3; return y + b + x2; }; - testSolidityAgainstCpp("run(uint256,uint256,uint256)", f, u256(0x1000), u256(0x10000), u256(0x100000)); + testContractAgainstCpp("run(uint256,uint256,uint256)", f, u256(0x1000), u256(0x10000), u256(0x100000)); } BOOST_AUTO_TEST_CASE(packing_unpacking_types) { - char const* sourceCode = "contract test {\n" - " function run(bool a, uint32 b, uint64 c) returns(uint256 y) {\n" - " if (a) y = 1;\n" - " y = y * 0x100000000 | ~b;\n" - " y = y * 0x10000000000000000 | ~c;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function run(bool a, uint32 b, uint64 c) returns(uint256 y) { + if (a) y = 1; + y = y * 0x100000000 | ~b; + y = y * 0x10000000000000000 | ~c; + } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("run(bool,uint32,uint64)", true, fromHex("0f0f0f0f"), fromHex("f0f0f0f0f0f0f0f0")) == fromHex("00000000000000000000000000000000000000""01""f0f0f0f0""0f0f0f0f0f0f0f0f")); @@ -635,12 +671,14 @@ BOOST_AUTO_TEST_CASE(packing_unpacking_types) BOOST_AUTO_TEST_CASE(packing_signed_types) { - char const* sourceCode = "contract test {\n" - " function run() returns(int8 y) {\n" - " uint8 x = 0xfa;\n" - " return int8(x);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function run() returns(int8 y) { + uint8 x = 0xfa; + return int8(x); + } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("run()") == fromHex("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa")); @@ -648,23 +686,27 @@ BOOST_AUTO_TEST_CASE(packing_signed_types) BOOST_AUTO_TEST_CASE(multiple_return_values) { - char const* sourceCode = "contract test {\n" - " function run(bool x1, uint x2) returns(uint y1, bool y2, uint y3) {\n" - " y1 = x2; y2 = x1;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function run(bool x1, uint x2) returns(uint y1, bool y2, uint y3) { + y1 = x2; y2 = x1; + } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("run(bool,uint256)", true, 0xcd) == encodeArgs(0xcd, true, 0)); } BOOST_AUTO_TEST_CASE(short_circuiting) { - char const* sourceCode = "contract test {\n" - " function run(uint x) returns(uint y) {\n" - " x == 0 || ((x = 8) > 0);\n" - " return x;" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function run(uint x) returns(uint y) { + x == 0 || ((x = 8) > 0); + return x; + } + } + )"; compileAndRun(sourceCode); auto short_circuiting_cpp = [](u256 n) -> u256 @@ -673,19 +715,21 @@ BOOST_AUTO_TEST_CASE(short_circuiting) return n; }; - testSolidityAgainstCppOnRange("run(uint256)", short_circuiting_cpp, 0, 2); + testContractAgainstCppOnRange("run(uint256)", short_circuiting_cpp, 0, 2); } BOOST_AUTO_TEST_CASE(high_bits_cleaning) { - char const* sourceCode = "contract test {\n" - " function run() returns(uint256 y) {\n" - " uint32 t = uint32(0xffffffff);\n" - " uint32 x = t + 10;\n" - " if (x >= 0xffffffff) return 0;\n" - " return x;" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function run() returns(uint256 y) { + uint32 t = uint32(0xffffffff); + uint32 x = t + 10; + if (x >= 0xffffffff) return 0; + return x; + } + } + )"; compileAndRun(sourceCode); auto high_bits_cleaning_cpp = []() -> u256 { @@ -695,18 +739,20 @@ BOOST_AUTO_TEST_CASE(high_bits_cleaning) return 0; return x; }; - testSolidityAgainstCpp("run()", high_bits_cleaning_cpp); + testContractAgainstCpp("run()", high_bits_cleaning_cpp); } BOOST_AUTO_TEST_CASE(sign_extension) { - char const* sourceCode = "contract test {\n" - " function run() returns(uint256 y) {\n" - " int64 x = -int32(0xff);\n" - " if (x >= 0xff) return 0;\n" - " return -uint256(x);" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function run() returns(uint256 y) { + int64 x = -int32(0xff); + if (x >= 0xff) return 0; + return -uint256(x); + } + } + )"; compileAndRun(sourceCode); auto sign_extension_cpp = []() -> u256 { @@ -715,18 +761,20 @@ BOOST_AUTO_TEST_CASE(sign_extension) return 0; return u256(x) * -1; }; - testSolidityAgainstCpp("run()", sign_extension_cpp); + testContractAgainstCpp("run()", sign_extension_cpp); } BOOST_AUTO_TEST_CASE(small_unsigned_types) { - char const* sourceCode = "contract test {\n" - " function run() returns(uint256 y) {\n" - " uint32 t = uint32(0xffffff);\n" - " uint32 x = t * 0xffffff;\n" - " return x / 0x100;" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function run() returns(uint256 y) { + uint32 t = uint32(0xffffff); + uint32 x = t * 0xffffff; + return x / 0x100; + } + } + )"; compileAndRun(sourceCode); auto small_unsigned_types_cpp = []() -> u256 { @@ -734,35 +782,39 @@ BOOST_AUTO_TEST_CASE(small_unsigned_types) uint32_t x = t * 0xffffff; return x / 0x100; }; - testSolidityAgainstCpp("run()", small_unsigned_types_cpp); + testContractAgainstCpp("run()", small_unsigned_types_cpp); } BOOST_AUTO_TEST_CASE(small_signed_types) { - char const* sourceCode = "contract test {\n" - " function run() returns(int256 y) {\n" - " return -int32(10) * -int64(20);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function run() returns(int256 y) { + return -int32(10) * -int64(20); + } + } + )"; compileAndRun(sourceCode); auto small_signed_types_cpp = []() -> u256 { return -int32_t(10) * -int64_t(20); }; - testSolidityAgainstCpp("run()", small_signed_types_cpp); + testContractAgainstCpp("run()", small_signed_types_cpp); } BOOST_AUTO_TEST_CASE(strings) { - char const* sourceCode = "contract test {\n" - " function fixedBytes() returns(bytes32 ret) {\n" - " return \"abc\\x00\\xff__\";\n" - " }\n" - " function pipeThrough(bytes2 small, bool one) returns(bytes16 large, bool oneRet) {\n" - " oneRet = one;\n" - " large = small;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function fixedBytes() returns(bytes32 ret) { + return "abc\x00\xff__"; + } + function pipeThrough(bytes2 small, bool one) returns(bytes16 large, bool oneRet) { + oneRet = one; + large = small; + } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("fixedBytes()") == encodeArgs(string("abc\0\xff__", 7))); BOOST_CHECK(callContractFunction("pipeThrough(bytes2,bool)", string("\0\x02", 2), true) == encodeArgs(string("\0\x2", 2), true)); @@ -807,18 +859,20 @@ BOOST_AUTO_TEST_CASE(bytes_comparison) BOOST_AUTO_TEST_CASE(state_smoke_test) { - char const* sourceCode = "contract test {\n" - " uint256 value1;\n" - " uint256 value2;\n" - " function get(uint8 which) returns (uint256 value) {\n" - " if (which == 0) return value1;\n" - " else return value2;\n" - " }\n" - " function set(uint8 which, uint256 value) {\n" - " if (which == 0) value1 = value;\n" - " else value2 = value;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + uint256 value1; + uint256 value2; + function get(uint8 which) returns (uint256 value) { + if (which == 0) return value1; + else return value2; + } + function set(uint8 which, uint256 value) { + if (which == 0) value1 = value; + else value2 = value; + } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("get(uint8)", byte(0x00)) == encodeArgs(0)); BOOST_CHECK(callContractFunction("get(uint8)", byte(0x01)) == encodeArgs(0)); @@ -832,17 +886,19 @@ BOOST_AUTO_TEST_CASE(state_smoke_test) BOOST_AUTO_TEST_CASE(compound_assign) { - char const* sourceCode = "contract test {\n" - " uint value1;\n" - " uint value2;\n" - " function f(uint x, uint y) returns (uint w) {\n" - " uint value3 = y;" - " value1 += x;\n" - " value3 *= x;" - " value2 *= value3 + value1;\n" - " return value2 += 7;" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + uint value1; + uint value2; + function f(uint x, uint y) returns (uint w) { + uint value3 = y; + value1 += x; + value3 *= x; + value2 *= value3 + value1; + return value2 += 7; + } + } + )"; compileAndRun(sourceCode); u256 value1; @@ -855,27 +911,29 @@ BOOST_AUTO_TEST_CASE(compound_assign) value2 *= value3 + value1; return value2 += 7; }; - testSolidityAgainstCpp("f(uint256,uint256)", f, u256(0), u256(6)); - testSolidityAgainstCpp("f(uint256,uint256)", f, u256(1), u256(3)); - testSolidityAgainstCpp("f(uint256,uint256)", f, u256(2), u256(25)); - testSolidityAgainstCpp("f(uint256,uint256)", f, u256(3), u256(69)); - testSolidityAgainstCpp("f(uint256,uint256)", f, u256(4), u256(84)); - testSolidityAgainstCpp("f(uint256,uint256)", f, u256(5), u256(2)); - testSolidityAgainstCpp("f(uint256,uint256)", f, u256(6), u256(51)); - testSolidityAgainstCpp("f(uint256,uint256)", f, u256(7), u256(48)); + testContractAgainstCpp("f(uint256,uint256)", f, u256(0), u256(6)); + testContractAgainstCpp("f(uint256,uint256)", f, u256(1), u256(3)); + testContractAgainstCpp("f(uint256,uint256)", f, u256(2), u256(25)); + testContractAgainstCpp("f(uint256,uint256)", f, u256(3), u256(69)); + testContractAgainstCpp("f(uint256,uint256)", f, u256(4), u256(84)); + testContractAgainstCpp("f(uint256,uint256)", f, u256(5), u256(2)); + testContractAgainstCpp("f(uint256,uint256)", f, u256(6), u256(51)); + testContractAgainstCpp("f(uint256,uint256)", f, u256(7), u256(48)); } BOOST_AUTO_TEST_CASE(simple_mapping) { - char const* sourceCode = "contract test {\n" - " mapping(uint8 => uint8) table;\n" - " function get(uint8 k) returns (uint8 v) {\n" - " return table[k];\n" - " }\n" - " function set(uint8 k, uint8 v) {\n" - " table[k] = v;\n" - " }\n" - "}"; + char const* sourceCode = R"( + contract test { + mapping(uint8 => uint8) table; + function get(uint8 k) returns (uint8 v) { + return table[k]; + } + function set(uint8 k, uint8 v) { + table[k] = v; + } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("get(uint8)", byte(0)) == encodeArgs(byte(0x00))); @@ -897,23 +955,25 @@ BOOST_AUTO_TEST_CASE(simple_mapping) BOOST_AUTO_TEST_CASE(mapping_state) { - char const* sourceCode = "contract Ballot {\n" - " mapping(address => bool) canVote;\n" - " mapping(address => uint) voteCount;\n" - " mapping(address => bool) voted;\n" - " function getVoteCount(address addr) returns (uint retVoteCount) {\n" - " return voteCount[addr];\n" - " }\n" - " function grantVoteRight(address addr) {\n" - " canVote[addr] = true;\n" - " }\n" - " function vote(address voter, address vote) returns (bool success) {\n" - " if (!canVote[voter] || voted[voter]) return false;\n" - " voted[voter] = true;\n" - " voteCount[vote] = voteCount[vote] + 1;\n" - " return true;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract Ballot { + mapping(address => bool) canVote; + mapping(address => uint) voteCount; + mapping(address => bool) voted; + function getVoteCount(address addr) returns (uint retVoteCount) { + return voteCount[addr]; + } + function grantVoteRight(address addr) { + canVote[addr] = true; + } + function vote(address voter, address vote) returns (bool success) { + if (!canVote[voter] || voted[voter]) return false; + voted[voter] = true; + voteCount[vote] = voteCount[vote] + 1; + return true; + } + } + )"; compileAndRun(sourceCode); class Ballot { @@ -936,53 +996,55 @@ BOOST_AUTO_TEST_CASE(mapping_state) auto getVoteCount = bind(&Ballot::getVoteCount, &ballot, _1); auto grantVoteRight = bind(&Ballot::grantVoteRight, &ballot, _1); auto vote = bind(&Ballot::vote, &ballot, _1, _2); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(0)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(1)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(2)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(0)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(1)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(2)); // voting without vote right should be rejected - testSolidityAgainstCpp("vote(address,address)", vote, u160(0), u160(2)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(0)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(1)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(2)); + testContractAgainstCpp("vote(address,address)", vote, u160(0), u160(2)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(0)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(1)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(2)); // grant vote rights - testSolidityAgainstCpp("grantVoteRight(address)", grantVoteRight, u160(0)); - testSolidityAgainstCpp("grantVoteRight(address)", grantVoteRight, u160(1)); + testContractAgainstCpp("grantVoteRight(address)", grantVoteRight, u160(0)); + testContractAgainstCpp("grantVoteRight(address)", grantVoteRight, u160(1)); // vote, should increase 2's vote count - testSolidityAgainstCpp("vote(address,address)", vote, u160(0), u160(2)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(0)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(1)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(2)); + testContractAgainstCpp("vote(address,address)", vote, u160(0), u160(2)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(0)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(1)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(2)); // vote again, should be rejected - testSolidityAgainstCpp("vote(address,address)", vote, u160(0), u160(1)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(0)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(1)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(2)); + testContractAgainstCpp("vote(address,address)", vote, u160(0), u160(1)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(0)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(1)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(2)); // vote without right to vote - testSolidityAgainstCpp("vote(address,address)", vote, u160(2), u160(1)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(0)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(1)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(2)); + testContractAgainstCpp("vote(address,address)", vote, u160(2), u160(1)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(0)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(1)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(2)); // grant vote right and now vote again - testSolidityAgainstCpp("grantVoteRight(address)", grantVoteRight, u160(2)); - testSolidityAgainstCpp("vote(address,address)", vote, u160(2), u160(1)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(0)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(1)); - testSolidityAgainstCpp("getVoteCount(address)", getVoteCount, u160(2)); + testContractAgainstCpp("grantVoteRight(address)", grantVoteRight, u160(2)); + testContractAgainstCpp("vote(address,address)", vote, u160(2), u160(1)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(0)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(1)); + testContractAgainstCpp("getVoteCount(address)", getVoteCount, u160(2)); } BOOST_AUTO_TEST_CASE(mapping_state_inc_dec) { - char const* sourceCode = "contract test {\n" - " uint value;\n" - " mapping(uint => uint) table;\n" - " function f(uint x) returns (uint y) {\n" - " value = x;\n" - " if (x > 0) table[++value] = 8;\n" - " if (x > 1) value--;\n" - " if (x > 2) table[value]++;\n" - " return --table[value++];\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + uint value; + mapping(uint => uint) table; + function f(uint x) returns (uint y) { + value = x; + if (x > 0) table[++value] = 8; + if (x > 1) value--; + if (x > 2) table[value]++; + return --table[value++]; + } + } + )"; compileAndRun(sourceCode); u256 value = 0; @@ -998,18 +1060,20 @@ BOOST_AUTO_TEST_CASE(mapping_state_inc_dec) table[value]++; return --table[value++]; }; - testSolidityAgainstCppOnRange("f(uint256)", f, 0, 5); + testContractAgainstCppOnRange("f(uint256)", f, 0, 5); } BOOST_AUTO_TEST_CASE(multi_level_mapping) { - char const* sourceCode = "contract test {\n" - " mapping(uint => mapping(uint => uint)) table;\n" - " function f(uint x, uint y, uint z) returns (uint w) {\n" - " if (z == 0) return table[x][y];\n" - " else return table[x][y] = z;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + mapping(uint => mapping(uint => uint)) table; + function f(uint x, uint y, uint z) returns (uint w) { + if (z == 0) return table[x][y]; + else return table[x][y] = z; + } + } + )"; compileAndRun(sourceCode); map<u256, map<u256, u256>> table; @@ -1018,47 +1082,49 @@ BOOST_AUTO_TEST_CASE(multi_level_mapping) if (_z == 0) return table[_x][_y]; else return table[_x][_y] = _z; }; - testSolidityAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(0)); - testSolidityAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(0)); - testSolidityAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(9)); - testSolidityAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(0)); - testSolidityAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(0)); - testSolidityAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(7)); - testSolidityAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(0)); - testSolidityAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(0)); + testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(0)); + testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(0)); + testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(9)); + testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(0)); + testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(0)); + testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(7)); + testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(4), u256(5), u256(0)); + testContractAgainstCpp("f(uint256,uint256,uint256)", f, u256(5), u256(4), u256(0)); } BOOST_AUTO_TEST_CASE(structs) { - char const* sourceCode = "contract test {\n" - " struct s1 {\n" - " uint8 x;\n" - " bool y;\n" - " }\n" - " struct s2 {\n" - " uint32 z;\n" - " s1 s1data;\n" - " mapping(uint8 => s2) recursive;\n" - " }\n" - " s2 data;\n" - " function check() returns (bool ok) {\n" - " return data.z == 1 && data.s1data.x == 2 && \n" - " data.s1data.y == true && \n" - " data.recursive[3].recursive[4].z == 5 && \n" - " data.recursive[4].recursive[3].z == 6 && \n" - " data.recursive[0].s1data.y == false && \n" - " data.recursive[4].z == 9;\n" - " }\n" - " function set() {\n" - " data.z = 1;\n" - " data.s1data.x = 2;\n" - " data.s1data.y = true;\n" - " data.recursive[3].recursive[4].z = 5;\n" - " data.recursive[4].recursive[3].z = 6;\n" - " data.recursive[0].s1data.y = false;\n" - " data.recursive[4].z = 9;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + struct s1 { + uint8 x; + bool y; + } + struct s2 { + uint32 z; + s1 s1data; + mapping(uint8 => s2) recursive; + } + s2 data; + function check() returns (bool ok) { + return data.z == 1 && data.s1data.x == 2 && + data.s1data.y == true && + data.recursive[3].recursive[4].z == 5 && + data.recursive[4].recursive[3].z == 6 && + data.recursive[0].s1data.y == false && + data.recursive[4].z == 9; + } + function set() { + data.z = 1; + data.s1data.x = 2; + data.s1data.y = true; + data.recursive[3].recursive[4].z = 5; + data.recursive[4].recursive[3].z = 6; + data.recursive[0].s1data.y = false; + data.recursive[4].z = 9; + } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("check()") == encodeArgs(false)); BOOST_CHECK(callContractFunction("set()") == bytes()); @@ -1067,26 +1133,28 @@ BOOST_AUTO_TEST_CASE(structs) BOOST_AUTO_TEST_CASE(struct_reference) { - char const* sourceCode = "contract test {\n" - " struct s2 {\n" - " uint32 z;\n" - " mapping(uint8 => s2) recursive;\n" - " }\n" - " s2 data;\n" - " function check() returns (bool ok) {\n" - " return data.z == 2 && \n" - " data.recursive[0].z == 3 && \n" - " data.recursive[0].recursive[1].z == 0 && \n" - " data.recursive[0].recursive[0].z == 1;\n" - " }\n" - " function set() {\n" - " data.z = 2;\n" - " var map = data.recursive;\n" - " s2 inner = map[0];\n" - " inner.z = 3;\n" - " inner.recursive[0].z = inner.recursive[1].z + 1;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + struct s2 { + uint32 z; + mapping(uint8 => s2) recursive; + } + s2 data; + function check() returns (bool ok) { + return data.z == 2 && + data.recursive[0].z == 3 && + data.recursive[0].recursive[1].z == 0 && + data.recursive[0].recursive[0].z == 1; + } + function set() { + data.z = 2; + var map = data.recursive; + s2 inner = map[0]; + inner.z = 3; + inner.recursive[0].z = inner.recursive[1].z + 1; + } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("check()") == encodeArgs(false)); BOOST_CHECK(callContractFunction("set()") == bytes()); @@ -1133,12 +1201,13 @@ BOOST_AUTO_TEST_CASE(deleteStruct) nestedValue = str.nstr.nestedValue; } function getTopMapping(uint index) returns(uint ret) { - ret = str.topMapping[index]; + ret = str.topMapping[index]; } function getNestedMapping(uint index) returns(bool ret) { return str.nstr.nestedMapping[index]; } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("getToDelete()") == encodeArgs(0)); BOOST_CHECK(callContractFunction("getTopValue()") == encodeArgs(0)); @@ -1159,7 +1228,8 @@ BOOST_AUTO_TEST_CASE(deleteLocal) delete v; res = v; } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("delLocal()") == encodeArgs(0)); } @@ -1176,22 +1246,25 @@ BOOST_AUTO_TEST_CASE(deleteLocals) res1 = w; res2 = x; } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("delLocal()") == encodeArgs(6, 7)); } BOOST_AUTO_TEST_CASE(constructor) { - char const* sourceCode = "contract test {\n" - " mapping(uint => uint) data;\n" - " function test() {\n" - " data[7] = 8;\n" - " }\n" - " function get(uint key) returns (uint value) {\n" - " return data[key];" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + mapping(uint => uint) data; + function test() { + data[7] = 8; + } + function get(uint key) returns (uint value) { + return data[key]; + } + } + )"; compileAndRun(sourceCode); map<u256, byte> data; data[7] = 8; @@ -1199,18 +1272,20 @@ BOOST_AUTO_TEST_CASE(constructor) { return data[_x]; }; - testSolidityAgainstCpp("get(uint256)", get, u256(6)); - testSolidityAgainstCpp("get(uint256)", get, u256(7)); + testContractAgainstCpp("get(uint256)", get, u256(6)); + testContractAgainstCpp("get(uint256)", get, u256(7)); } BOOST_AUTO_TEST_CASE(simple_accessor) { - char const* sourceCode = "contract test {\n" - " uint256 public data;\n" - " function test() {\n" - " data = 8;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + uint256 public data; + function test() { + data = 8; + } + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("data()") == encodeArgs(8)); } @@ -1252,7 +1327,7 @@ BOOST_AUTO_TEST_CASE(array_accessor) BOOST_AUTO_TEST_CASE(accessors_mapping_for_array) { char const* sourceCode = R"( - contract test { + contract test { mapping(uint => uint[8]) public data; mapping(uint => uint[]) public dynamicData; function test() { @@ -1260,7 +1335,7 @@ BOOST_AUTO_TEST_CASE(accessors_mapping_for_array) dynamicData[2].length = 3; dynamicData[2][2] = 8; } - } + } )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("data(uint256,uint256)", 2, 2) == encodeArgs(8)); @@ -1271,20 +1346,22 @@ BOOST_AUTO_TEST_CASE(accessors_mapping_for_array) BOOST_AUTO_TEST_CASE(multiple_elementary_accessors) { - char const* sourceCode = "contract test {\n" - " uint256 public data;\n" - " bytes6 public name;\n" - " bytes32 public a_hash;\n" - " address public an_address;\n" - " function test() {\n" - " data = 8;\n" - " name = \"Celina\";\n" - " a_hash = sha3(123);\n" - " an_address = address(0x1337);\n" - " super_secret_data = 42;\n" - " }\n" - " uint256 super_secret_data;" - "}\n"; + char const* sourceCode = R"( + contract test { + uint256 public data; + bytes6 public name; + bytes32 public a_hash; + address public an_address; + function test() { + data = 8; + name = "Celina"; + a_hash = sha3(123); + an_address = address(0x1337); + super_secret_data = 42; + } + uint256 super_secret_data; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("data()") == encodeArgs(8)); BOOST_CHECK(callContractFunction("name()") == encodeArgs("Celina")); @@ -1336,26 +1413,30 @@ BOOST_AUTO_TEST_CASE(struct_accessor) BOOST_AUTO_TEST_CASE(balance) { - char const* sourceCode = "contract test {\n" - " function test() payable {}\n" - " function getBalance() returns (uint256 balance) {\n" - " return address(this).balance;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function test() payable {} + function getBalance() returns (uint256 balance) { + return address(this).balance; + } + } + )"; compileAndRun(sourceCode, 23); BOOST_CHECK(callContractFunction("getBalance()") == encodeArgs(23)); } BOOST_AUTO_TEST_CASE(blockchain) { - char const* sourceCode = "contract test {\n" - " function test() payable {}\n" - " function someInfo() payable returns (uint256 value, address coinbase, uint256 blockNumber) {\n" - " value = msg.value;\n" - " coinbase = block.coinbase;\n" - " blockNumber = block.number;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function test() payable {} + function someInfo() payable returns (uint256 value, address coinbase, uint256 blockNumber) { + value = msg.value; + coinbase = block.coinbase; + blockNumber = block.number; + } + } + )"; BOOST_CHECK(m_rpc.rpcCall("miner_setEtherbase", {"\"0x1212121212121212121212121212121212121212\""}).asBool() == true); m_rpc.test_mineBlocks(5); compileAndRun(sourceCode, 27); @@ -1393,12 +1474,14 @@ BOOST_AUTO_TEST_CASE(msg_sig_after_internal_call_is_same) BOOST_AUTO_TEST_CASE(now) { - char const* sourceCode = "contract test {\n" - " function someInfo() returns (bool equal, uint val) {\n" - " equal = block.timestamp == now;\n" - " val = now;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function someInfo() returns (bool equal, uint val) { + equal = block.timestamp == now; + val = now; + } + } + )"; m_rpc.test_modifyTimestamp(0x776347e2); compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("someInfo()") == encodeArgs(true, 0x776347e3)); @@ -1411,7 +1494,8 @@ BOOST_AUTO_TEST_CASE(type_conversions_cleanup) char const* sourceCode = R"( contract Test { function test() returns (uint ret) { return uint(address(Test(address(0x11223344556677889900112233445566778899001122)))); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_REQUIRE(callContractFunction("test()") == bytes({0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0x11, 0x22, @@ -1425,7 +1509,8 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_fixed_bytes_smaller_size) function bytesToBytes(bytes4 input) returns (bytes2 ret) { return bytes2(input); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("bytesToBytes(bytes4)", "abcd") == encodeArgs("ab")); } @@ -1437,7 +1522,8 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_fixed_bytes_greater_size) function bytesToBytes(bytes2 input) returns (bytes4 ret) { return bytes4(input); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("bytesToBytes(bytes2)", "ab") == encodeArgs("ab")); } @@ -1449,7 +1535,8 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_fixed_bytes_same_size) function bytesToBytes(bytes4 input) returns (bytes4 ret) { return bytes4(input); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("bytesToBytes(bytes4)", "abcd") == encodeArgs("abcd")); } @@ -1462,7 +1549,8 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_same_size) function bytesToUint(bytes32 s) returns (uint256 h) { return uint(s); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("bytesToUint(bytes32)", string("abc2")) == encodeArgs(u256("0x6162633200000000000000000000000000000000000000000000000000000000"))); @@ -1475,7 +1563,8 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_same_min_size) function bytesToUint(bytes1 s) returns (uint8 h) { return uint8(s); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("bytesToUint(bytes1)", string("a")) == encodeArgs(u256("0x61"))); @@ -1488,7 +1577,8 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_smaller_size) function bytesToUint(bytes4 s) returns (uint16 h) { return uint16(s); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("bytesToUint(bytes4)", string("abcd")) == encodeArgs(u256("0x6364"))); @@ -1501,7 +1591,8 @@ BOOST_AUTO_TEST_CASE(convert_fixed_bytes_to_uint_greater_size) function bytesToUint(bytes4 s) returns (uint64 h) { return uint64(s); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("bytesToUint(bytes4)", string("abcd")) == encodeArgs(u256("0x61626364"))); @@ -1515,7 +1606,8 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_same_size) function uintToBytes(uint256 h) returns (bytes32 s) { return bytes32(h); } - })"; + } + )"; compileAndRun(sourceCode); u256 a("0x6162630000000000000000000000000000000000000000000000000000000000"); BOOST_CHECK(callContractFunction("uintToBytes(uint256)", a) == encodeArgs(a)); @@ -1528,7 +1620,8 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_same_min_size) function UintToBytes(uint8 h) returns (bytes1 s) { return bytes1(h); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("UintToBytes(uint8)", u256("0x61")) == encodeArgs(string("a"))); @@ -1541,7 +1634,8 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_smaller_size) function uintToBytes(uint32 h) returns (bytes2 s) { return bytes2(h); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("uintToBytes(uint32)", u160("0x61626364")) == encodeArgs(string("cd"))); @@ -1554,7 +1648,8 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_greater_size) function UintToBytes(uint16 h) returns (bytes8 s) { return bytes8(h); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK( callContractFunction("UintToBytes(uint16)", u256("0x6162")) == @@ -1564,13 +1659,15 @@ BOOST_AUTO_TEST_CASE(convert_uint_to_fixed_bytes_greater_size) BOOST_AUTO_TEST_CASE(send_ether) { - char const* sourceCode = "contract test {\n" - " function test() payable {}\n" - " function a(address addr, uint amount) returns (uint ret) {\n" - " addr.send(amount);\n" - " return address(this).balance;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function test() payable {} + function a(address addr, uint amount) returns (uint ret) { + addr.send(amount); + return address(this).balance; + } + } + )"; u256 amount(130); compileAndRun(sourceCode, amount + 1); u160 address(23); @@ -1580,11 +1677,13 @@ BOOST_AUTO_TEST_CASE(send_ether) BOOST_AUTO_TEST_CASE(log0) { - char const* sourceCode = "contract test {\n" - " function a() {\n" - " log0(1);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a() { + log0(1); + } + } + )"; compileAndRun(sourceCode); callContractFunction("a()"); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); @@ -1595,11 +1694,13 @@ BOOST_AUTO_TEST_CASE(log0) BOOST_AUTO_TEST_CASE(log1) { - char const* sourceCode = "contract test {\n" - " function a() {\n" - " log1(1, 2);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a() { + log1(1, 2); + } + } + )"; compileAndRun(sourceCode); callContractFunction("a()"); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); @@ -1611,11 +1712,13 @@ BOOST_AUTO_TEST_CASE(log1) BOOST_AUTO_TEST_CASE(log2) { - char const* sourceCode = "contract test {\n" - " function a() {\n" - " log2(1, 2, 3);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a() { + log2(1, 2, 3); + } + } + )"; compileAndRun(sourceCode); callContractFunction("a()"); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); @@ -1628,11 +1731,13 @@ BOOST_AUTO_TEST_CASE(log2) BOOST_AUTO_TEST_CASE(log3) { - char const* sourceCode = "contract test {\n" - " function a() {\n" - " log3(1, 2, 3, 4);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a() { + log3(1, 2, 3, 4); + } + } + )"; compileAndRun(sourceCode); callContractFunction("a()"); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); @@ -1645,11 +1750,13 @@ BOOST_AUTO_TEST_CASE(log3) BOOST_AUTO_TEST_CASE(log4) { - char const* sourceCode = "contract test {\n" - " function a() {\n" - " log4(1, 2, 3, 4, 5);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a() { + log4(1, 2, 3, 4, 5); + } + } + )"; compileAndRun(sourceCode); callContractFunction("a()"); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); @@ -1662,11 +1769,13 @@ BOOST_AUTO_TEST_CASE(log4) BOOST_AUTO_TEST_CASE(log_in_constructor) { - char const* sourceCode = "contract test {\n" - " function test() {\n" - " log1(1, 2);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function test() { + log1(1, 2); + } + } + )"; compileAndRun(sourceCode); BOOST_REQUIRE_EQUAL(m_logs.size(), 1); BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); @@ -1677,13 +1786,15 @@ BOOST_AUTO_TEST_CASE(log_in_constructor) BOOST_AUTO_TEST_CASE(suicide) { - char const* sourceCode = "contract test {\n" - " function test() payable {}\n" - " function a(address receiver) returns (uint ret) {\n" - " suicide(receiver);\n" - " return 10;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function test() payable {} + function a(address receiver) returns (uint ret) { + suicide(receiver); + return 10; + } + } + )"; u256 amount(130); compileAndRun(sourceCode, amount); u160 address(23); @@ -1694,13 +1805,15 @@ BOOST_AUTO_TEST_CASE(suicide) BOOST_AUTO_TEST_CASE(selfdestruct) { - char const* sourceCode = "contract test {\n" - " function test() payable {}\n" - " function a(address receiver) returns (uint ret) {\n" - " selfdestruct(receiver);\n" - " return 10;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function test() payable {} + function a(address receiver) returns (uint ret) { + selfdestruct(receiver); + return 10; + } + } + )"; u256 amount(130); compileAndRun(sourceCode, amount); u160 address(23); @@ -1711,28 +1824,32 @@ BOOST_AUTO_TEST_CASE(selfdestruct) BOOST_AUTO_TEST_CASE(sha3) { - char const* sourceCode = "contract test {\n" - " function a(bytes32 input) returns (bytes32 sha3hash) {\n" - " return sha3(input);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a(bytes32 input) returns (bytes32 sha3hash) { + return sha3(input); + } + } + )"; compileAndRun(sourceCode); auto f = [&](u256 const& _x) -> u256 { return dev::keccak256(toBigEndian(_x)); }; - testSolidityAgainstCpp("a(bytes32)", f, u256(4)); - testSolidityAgainstCpp("a(bytes32)", f, u256(5)); - testSolidityAgainstCpp("a(bytes32)", f, u256(-1)); + testContractAgainstCpp("a(bytes32)", f, u256(4)); + testContractAgainstCpp("a(bytes32)", f, u256(5)); + testContractAgainstCpp("a(bytes32)", f, u256(-1)); } BOOST_AUTO_TEST_CASE(sha256) { - char const* sourceCode = "contract test {\n" - " function a(bytes32 input) returns (bytes32 sha256hash) {\n" - " return sha256(input);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a(bytes32 input) returns (bytes32 sha256hash) { + return sha256(input); + } + } + )"; compileAndRun(sourceCode); auto f = [&](u256 const& _x) -> bytes { @@ -1744,18 +1861,20 @@ BOOST_AUTO_TEST_CASE(sha256) return fromHex("af9613760f72635fbdb44a5a0a63c39f12af30f950a6ee5c971be188e89c4051"); return fromHex(""); }; - testSolidityAgainstCpp("a(bytes32)", f, u256(4)); - testSolidityAgainstCpp("a(bytes32)", f, u256(5)); - testSolidityAgainstCpp("a(bytes32)", f, u256(-1)); + testContractAgainstCpp("a(bytes32)", f, u256(4)); + testContractAgainstCpp("a(bytes32)", f, u256(5)); + testContractAgainstCpp("a(bytes32)", f, u256(-1)); } BOOST_AUTO_TEST_CASE(ripemd) { - char const* sourceCode = "contract test {\n" - " function a(bytes32 input) returns (bytes32 sha256hash) {\n" - " return ripemd160(input);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a(bytes32 input) returns (bytes32 sha256hash) { + return ripemd160(input); + } + } + )"; compileAndRun(sourceCode); auto f = [&](u256 const& _x) -> bytes { @@ -1767,18 +1886,20 @@ BOOST_AUTO_TEST_CASE(ripemd) return fromHex("1cf4e77f5966e13e109703cd8a0df7ceda7f3dc3000000000000000000000000"); return fromHex(""); }; - testSolidityAgainstCpp("a(bytes32)", f, u256(4)); - testSolidityAgainstCpp("a(bytes32)", f, u256(5)); - testSolidityAgainstCpp("a(bytes32)", f, u256(-1)); + 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 = "contract test {\n" - " function a(bytes32 h, uint8 v, bytes32 r, bytes32 s) returns (address addr) {\n" - " return ecrecover(h, v, r, s);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function a(bytes32 h, uint8 v, bytes32 r, bytes32 s) returns (address addr) { + return ecrecover(h, v, r, s); + } + } + )"; compileAndRun(sourceCode); u256 h("0x18c547e4f7b0f325ad1e56f57e26c745b09a3e503d86e00e5255ff7f715d3d1c"); byte v = 28; @@ -2796,7 +2917,8 @@ BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one) ret_k = k; ret_g = g; } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("f(uint256,uint256)", 5, 9) != encodeArgs(5, 8)); BOOST_CHECK(callContractFunction("f(uint256,uint256)", 5, 9) == encodeArgs(9, 8)); @@ -2809,7 +2931,8 @@ BOOST_AUTO_TEST_CASE(empty_name_return_parameter) function f(uint k) returns(uint){ return k; } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("f(uint256)", 9) == encodeArgs(9)); } @@ -2822,7 +2945,8 @@ BOOST_AUTO_TEST_CASE(sha3_multiple_arguments) { d = sha3(a, b, c); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("foo(uint256,uint256,uint256)", 10, 12, 13) == encodeArgs( @@ -2840,7 +2964,8 @@ BOOST_AUTO_TEST_CASE(sha3_multiple_arguments_with_numeric_literals) { d = sha3(a, b, 145); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("foo(uint256,uint16)", 10, 12) == encodeArgs( @@ -2862,7 +2987,8 @@ BOOST_AUTO_TEST_CASE(sha3_multiple_arguments_with_string_literals) { d = sha3(a, b, 145, "foo"); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("foo()") == encodeArgs(dev::keccak256("foo"))); @@ -2888,7 +3014,8 @@ BOOST_AUTO_TEST_CASE(sha3_with_bytes) data[2] = "o"; return sha3(data) == sha3("foo"); } - })"; + } + )"; compileAndRun(sourceCode); BOOST_CHECK(callContractFunction("foo()") == encodeArgs(true)); } @@ -4464,6 +4591,34 @@ BOOST_AUTO_TEST_CASE(super_overload) BOOST_CHECK(callContractFunction("h()") == encodeArgs(2)); } +BOOST_AUTO_TEST_CASE(bool_conversion) +{ + char const* sourceCode = R"( + contract C { + function f(bool _b) returns(uint) { + if (_b) + return 1; + else + return 0; + } + function g(bool _in) returns (bool _out) { + _out = _in; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(bool)", 0) == encodeArgs(0)); + BOOST_CHECK(callContractFunction("f(bool)", 1) == encodeArgs(1)); + BOOST_CHECK(callContractFunction("f(bool)", 2) == encodeArgs(1)); + BOOST_CHECK(callContractFunction("f(bool)", 3) == encodeArgs(1)); + BOOST_CHECK(callContractFunction("f(bool)", 255) == encodeArgs(1)); + BOOST_CHECK(callContractFunction("g(bool)", 0) == encodeArgs(0)); + BOOST_CHECK(callContractFunction("g(bool)", 1) == encodeArgs(1)); + BOOST_CHECK(callContractFunction("g(bool)", 2) == encodeArgs(1)); + BOOST_CHECK(callContractFunction("g(bool)", 3) == encodeArgs(1)); + BOOST_CHECK(callContractFunction("g(bool)", 255) == encodeArgs(1)); +} + BOOST_AUTO_TEST_CASE(packed_storage_signed) { char const* sourceCode = R"( @@ -4506,6 +4661,102 @@ BOOST_AUTO_TEST_CASE(external_types_in_calls) BOOST_CHECK(callContractFunction("t2()") == encodeArgs(u256(9))); } +BOOST_AUTO_TEST_CASE(invalid_enum_compared) +{ + char const* sourceCode = R"( + contract C { + enum X { A, B } + + function test_eq() returns (bool) { + X garbled; + assembly { + garbled := 5 + } + return garbled == garbled; + } + function test_eq_ok() returns (bool) { + X garbled = X.A; + return garbled == garbled; + } + function test_neq() returns (bool) { + X garbled; + assembly { + garbled := 5 + } + return garbled != garbled; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("test_eq_ok()") == encodeArgs(u256(1))); + // both should throw + BOOST_CHECK(callContractFunction("test_eq()") == encodeArgs()); + BOOST_CHECK(callContractFunction("test_neq()") == encodeArgs()); +} + +BOOST_AUTO_TEST_CASE(invalid_enum_logged) +{ + char const* sourceCode = R"( + contract C { + enum X { A, B } + event Log(X); + + function test_log() returns (uint) { + X garbled = X.A; + assembly { + garbled := 5 + } + Log(garbled); + return 1; + } + function test_log_ok() returns (uint) { + X x = X.A; + Log(x); + return 1; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("test_log_ok()") == encodeArgs(u256(1))); + BOOST_REQUIRE_EQUAL(m_logs.size(), 1); + BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress); + BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1); + BOOST_REQUIRE_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Log(uint8)"))); + BOOST_CHECK_EQUAL(h256(m_logs[0].data), h256(u256(0))); + + // should throw + BOOST_CHECK(callContractFunction("test_log()") == encodeArgs()); +} + +BOOST_AUTO_TEST_CASE(invalid_enum_stored) +{ + char const* sourceCode = R"( + contract C { + enum X { A, B } + X public x; + + function test_store() returns (uint) { + X garbled = X.A; + assembly { + garbled := 5 + } + x = garbled; + return 1; + } + function test_store_ok() returns (uint) { + x = X.A; + return 1; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("test_store_ok()") == encodeArgs(u256(1))); + BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(0))); + + // should throw + BOOST_CHECK(callContractFunction("test_store()") == encodeArgs()); +} + BOOST_AUTO_TEST_CASE(invalid_enum_as_external_ret) { char const* sourceCode = R"( @@ -6324,17 +6575,6 @@ BOOST_AUTO_TEST_CASE(calldata_offset) BOOST_CHECK(callContractFunction("last()", encodeArgs()) == encodeDyn(string("nd"))); } -BOOST_AUTO_TEST_CASE(version_stamp_for_libraries) -{ - char const* sourceCode = "library lib {}"; - m_optimize = true; - bytes runtimeCode = compileAndRun(sourceCode, 0, "lib"); - BOOST_CHECK(runtimeCode.size() >= 8); - BOOST_CHECK_EQUAL(runtimeCode[0], int(Instruction::PUSH6)); // might change once we switch to 1.x.x - BOOST_CHECK_EQUAL(runtimeCode[1], 4); // might change once we switch away from x.4.x - BOOST_CHECK_EQUAL(runtimeCode[7], int(Instruction::POP)); -} - BOOST_AUTO_TEST_CASE(contract_binary_dependencies) { char const* sourceCode = R"( @@ -7608,13 +7848,6 @@ BOOST_AUTO_TEST_CASE(mem_resize_is_not_paid_at_call) u160 cAddr = m_contractAddress; compileAndRun(sourceCode, 0, "D"); BOOST_CHECK(callContractFunction("f(address)", cAddr) == encodeArgs(u256(7))); - - m_optimize = true; - - compileAndRun(sourceCode, 0, "C"); - u160 cAddrOpt = m_contractAddress; - compileAndRun(sourceCode, 0, "D"); - BOOST_CHECK(callContractFunction("f(address)", cAddrOpt) == encodeArgs(u256(7))); } BOOST_AUTO_TEST_CASE(calling_uninitialized_function) @@ -8223,6 +8456,396 @@ BOOST_AUTO_TEST_CASE(shift_negative_constant_right) BOOST_CHECK(callContractFunction("a()") == encodeArgs(u256(-0x42))); } +BOOST_AUTO_TEST_CASE(shift_left) +{ + char const* sourceCode = R"( + contract C { + function f(uint a, uint b) returns (uint) { + return a << b; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)) == encodeArgs(u256(0x426600))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)) == encodeArgs(u256(0x42660000))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)) == encodeArgs(u256(0x84cc0000))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(240)) == fromHex("4266000000000000000000000000000000000000000000000000000000000000")); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(256)) == encodeArgs(u256(0))); +} + +BOOST_AUTO_TEST_CASE(shift_left_uint32) +{ + char const* sourceCode = R"( + contract C { + function f(uint32 a, uint32 b) returns (uint) { + return a << b; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); + BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(8)) == encodeArgs(u256(0x426600))); + BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(16)) == encodeArgs(u256(0x42660000))); + BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(17)) == encodeArgs(u256(0x84cc0000))); + BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(32)) == encodeArgs(u256(0))); +} + +BOOST_AUTO_TEST_CASE(shift_left_uint8) +{ + char const* sourceCode = R"( + contract C { + function f(uint8 a, uint8 b) returns (uint) { + return a << b; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(0)) == encodeArgs(u256(0x66))); + BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(8)) == encodeArgs(u256(0))); +} + +BOOST_AUTO_TEST_CASE(shift_left_larger_type) +{ + // This basically tests proper cleanup and conversion. It should not convert x to int8. + char const* sourceCode = R"( + contract C { + function f() returns (int8) { + uint8 x = 254; + int8 y = 1; + return y << x; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0))); +} + +BOOST_AUTO_TEST_CASE(shift_left_assignment) +{ + char const* sourceCode = R"( + contract C { + function f(uint a, uint b) returns (uint) { + a <<= b; + return a; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)) == encodeArgs(u256(0x426600))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)) == encodeArgs(u256(0x42660000))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)) == encodeArgs(u256(0x84cc0000))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(240)) == fromHex("4266000000000000000000000000000000000000000000000000000000000000")); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(256)) == encodeArgs(u256(0))); +} + +BOOST_AUTO_TEST_CASE(shift_left_assignment_different_type) +{ + char const* sourceCode = R"( + contract C { + function f(uint a, uint8 b) returns (uint) { + a <<= b; + return a; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); + BOOST_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(8)) == encodeArgs(u256(0x426600))); + BOOST_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(16)) == encodeArgs(u256(0x42660000))); + BOOST_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(17)) == encodeArgs(u256(0x84cc0000))); + BOOST_CHECK(callContractFunction("f(uint256,uint8)", u256(0x4266), u256(240)) == fromHex("4266000000000000000000000000000000000000000000000000000000000000")); +} + +BOOST_AUTO_TEST_CASE(shift_right) +{ + char const* sourceCode = R"( + contract C { + function f(uint a, uint b) returns (uint) { + return a >> b; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)) == encodeArgs(u256(0x42))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)) == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)) == encodeArgs(u256(0))); +} + +BOOST_AUTO_TEST_CASE(shift_right_garbled) +{ + char const* sourceCode = R"( + contract C { + function f(uint8 a, uint8 b) returns (uint) { + assembly { + a := 0xffffffff + } + // Higher bits should be cleared before the shift + return a >> b; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x0), u256(4)) == encodeArgs(u256(0xf))); + BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x0), u256(0x1004)) == encodeArgs(u256(0xf))); +} + +BOOST_AUTO_TEST_CASE(shift_right_uint32) +{ + char const* sourceCode = R"( + contract C { + function f(uint32 a, uint32 b) returns (uint) { + return a >> b; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); + BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(8)) == encodeArgs(u256(0x42))); + BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(16)) == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("f(uint32,uint32)", u256(0x4266), u256(17)) == encodeArgs(u256(0))); +} + +BOOST_AUTO_TEST_CASE(shift_right_uint8) +{ + char const* sourceCode = R"( + contract C { + function f(uint8 a, uint8 b) returns (uint) { + return a >> b; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(0)) == encodeArgs(u256(0x66))); + BOOST_CHECK(callContractFunction("f(uint8,uint8)", u256(0x66), u256(8)) == encodeArgs(u256(0x0))); +} + +BOOST_AUTO_TEST_CASE(shift_right_assignment) +{ + char const* sourceCode = R"( + contract C { + function f(uint a, uint b) returns (uint) { + a >>= b; + return a; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(0)) == encodeArgs(u256(0x4266))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(8)) == encodeArgs(u256(0x42))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(16)) == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("f(uint256,uint256)", u256(0x4266), u256(17)) == encodeArgs(u256(0))); +} + +BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue) +{ + char const* sourceCode = R"( + contract C { + function f(int a, int b) returns (int) { + return a >> b; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(0)) == encodeArgs(u256(-4266))); + BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(8)) == encodeArgs(u256(-16))); + BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(16)) == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(17)) == encodeArgs(u256(0))); +} + +BOOST_AUTO_TEST_CASE(shift_right_negative_lvalue_assignment) +{ + char const* sourceCode = R"( + contract C { + function f(int a, int b) returns (int) { + a >>= b; + return a; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(0)) == encodeArgs(u256(-4266))); + BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(8)) == encodeArgs(u256(-16))); + BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(16)) == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("f(int256,int256)", u256(-4266), u256(17)) == encodeArgs(u256(0))); +} + +BOOST_AUTO_TEST_CASE(shift_negative_rvalue) +{ + char const* sourceCode = R"( + contract C { + function f(int a, int b) returns (int) { + return a << b; + } + function g(int a, int b) returns (int) { + return a >> b; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(int256,int256)", u256(1), u256(-1)) == encodeArgs()); + BOOST_CHECK(callContractFunction("g(int256,int256)", u256(1), u256(-1)) == encodeArgs()); +} + +BOOST_AUTO_TEST_CASE(shift_negative_rvalue_assignment) +{ + char const* sourceCode = R"( + contract C { + function f(int a, int b) returns (int) { + a <<= b; + return a; + } + function g(int a, int b) returns (int) { + a >>= b; + return a; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f(int256,int256)", u256(1), u256(-1)) == encodeArgs()); + BOOST_CHECK(callContractFunction("g(int256,int256)", u256(1), u256(-1)) == encodeArgs()); +} + +BOOST_AUTO_TEST_CASE(shift_constant_left_assignment) +{ + char const* sourceCode = R"( + contract C { + function f() returns (uint a) { + a = 0x42; + a <<= 8; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x4200))); +} + +BOOST_AUTO_TEST_CASE(shift_constant_right_assignment) +{ + char const* sourceCode = R"( + contract C { + function f() returns (uint a) { + a = 0x4200; + a >>= 8; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x42))); +} + +BOOST_AUTO_TEST_CASE(shift_cleanup) +{ + char const* sourceCode = R"( + contract C { + function f() returns (uint16 x) { + x = 0xffff; + x += 32; + x <<= 8; + x >>= 16; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x0))); +} + +BOOST_AUTO_TEST_CASE(shift_cleanup_garbled) +{ + char const* sourceCode = R"( + contract C { + function f() returns (uint8 x) { + assembly { + x := 0xffff + } + x >>= 8; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(0x0))); +} + +BOOST_AUTO_TEST_CASE(shift_overflow) +{ + char const* sourceCode = R"( + contract C { + function leftU(uint8 x, uint8 y) returns (uint8) { + return x << y; + } + function leftS(int8 x, int8 y) returns (int8) { + return x << y; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("leftU(uint8,uint8)", 255, 8) == encodeArgs(u256(0))); + BOOST_CHECK(callContractFunction("leftU(uint8,uint8)", 255, 1) == encodeArgs(u256(254))); + BOOST_CHECK(callContractFunction("leftU(uint8,uint8)", 255, 0) == encodeArgs(u256(255))); + + // Result is -128 and output is sign-extended, not zero-padded. + BOOST_CHECK(callContractFunction("leftS(int8,int8)", 1, 7) == encodeArgs(u256(0) - 128)); + BOOST_CHECK(callContractFunction("leftS(int8,int8)", 1, 6) == encodeArgs(u256(64))); +} + +BOOST_AUTO_TEST_CASE(shift_bytes) +{ + char const* sourceCode = R"( + contract C { + function left(bytes20 x, uint8 y) returns (bytes20) { + return x << y; + } + function right(bytes20 x, uint8 y) returns (bytes20) { + return x >> y; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("left(bytes20,uint8)", "12345678901234567890", 8 * 8) == encodeArgs("901234567890" + string(8, 0))); + BOOST_CHECK(callContractFunction("right(bytes20,uint8)", "12345678901234567890", 8 * 8) == encodeArgs(string(8, 0) + "123456789012")); +} + +BOOST_AUTO_TEST_CASE(shift_bytes_cleanup) +{ + char const* sourceCode = R"( + contract C { + function left(uint8 y) returns (bytes20) { + bytes20 x; + assembly { x := "12345678901234567890abcde" } + return x << y; + } + function right(uint8 y) returns (bytes20) { + bytes20 x; + assembly { x := "12345678901234567890abcde" } + return x >> y; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("left(uint8)", 8 * 8) == encodeArgs("901234567890" + string(8, 0))); + BOOST_CHECK(callContractFunction("right(uint8)", 8 * 8) == encodeArgs(string(8, 0) + "123456789012")); +} + +BOOST_AUTO_TEST_CASE(cleanup_in_compound_assign) +{ + char const* sourceCode = R"( + contract C { + function test() returns (uint, uint) { + uint32 a = 0xffffffff; + uint16 x = uint16(a); + uint16 y = x; + x /= 0x100; + y = y / 0x100; + return (x, y); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(0xff), u256(0xff))); +} + BOOST_AUTO_TEST_CASE(inline_assembly_in_modifiers) { char const* sourceCode = R"( @@ -8280,6 +8903,18 @@ BOOST_AUTO_TEST_CASE(inline_assembly_invalidjumplabel) BOOST_CHECK(callContractFunction("f()") == encodeArgs()); } +BOOST_AUTO_TEST_CASE(contracts_separated_with_comment) +{ + char const* sourceCode = R"( + contract C1 {} + /** + **/ + contract C2 {} + )"; + compileAndRun(sourceCode, 0, "C1"); + compileAndRun(sourceCode, 0, "C2"); +} + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityExecutionFramework.cpp b/test/libsolidity/SolidityExecutionFramework.cpp index 02548121..bb9695d1 100644 --- a/test/libsolidity/SolidityExecutionFramework.cpp +++ b/test/libsolidity/SolidityExecutionFramework.cpp @@ -1,18 +1,18 @@ /* - This file is part of cpp-ethereum. + This file is part of solidity. - cpp-ethereum is free software: you can redistribute it and/or modify + 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. - cpp-ethereum is distributed in the hope that it will be useful, + 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. + along with solidity. If not, see <http://www.gnu.org/licenses/>. */ /** * @author Christian <c@ethdev.com> @@ -22,115 +22,13 @@ #include <cstdlib> #include <boost/test/framework.hpp> -#include <libdevcore/CommonIO.h> #include <test/libsolidity/SolidityExecutionFramework.h> -using namespace std; -using namespace dev; +using namespace dev::test; using namespace dev::solidity; using namespace dev::solidity::test; -namespace // anonymous +SolidityExecutionFramework::SolidityExecutionFramework() : + ExecutionFramework() { - h256 const EmptyTrie("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421"); -} - -string getIPCSocketPath() -{ - string ipcPath = dev::test::Options::get().ipcPath; - if (ipcPath.empty()) - BOOST_FAIL("ERROR: ipcPath not set! (use --ipcpath <path> or the environment variable ETH_TEST_IPC)"); - - return ipcPath; -} - -ExecutionFramework::ExecutionFramework() : - m_rpc(RPCSession::instance(getIPCSocketPath())), - m_sender(m_rpc.account(0)) -{ - m_rpc.test_rewindToBlock(0); -} - -void ExecutionFramework::sendMessage(bytes const& _data, bool _isCreation, u256 const& _value) -{ - RPCSession::TransactionData d; - d.data = "0x" + toHex(_data); - d.from = "0x" + toString(m_sender); - d.gas = toHex(m_gas, HexPrefix::Add); - d.gasPrice = toHex(m_gasPrice, HexPrefix::Add); - d.value = toHex(_value, HexPrefix::Add); - if (!_isCreation) - { - d.to = dev::toString(m_contractAddress); - BOOST_REQUIRE(m_rpc.eth_getCode(d.to, "latest").size() > 2); - // Use eth_call to get the output - m_output = fromHex(m_rpc.eth_call(d, "latest"), WhenError::Throw); - } - - string txHash = m_rpc.eth_sendTransaction(d); - m_rpc.test_mineBlocks(1); - RPCSession::TransactionReceipt receipt(m_rpc.eth_getTransactionReceipt(txHash)); - - if (_isCreation) - { - m_contractAddress = Address(receipt.contractAddress); - BOOST_REQUIRE(m_contractAddress); - string code = m_rpc.eth_getCode(receipt.contractAddress, "latest"); - m_output = fromHex(code, WhenError::Throw); - } - - m_gasUsed = u256(receipt.gasUsed); - m_logs.clear(); - for (auto const& log: receipt.logEntries) - { - LogEntry entry; - entry.address = Address(log.address); - for (auto const& topic: log.topics) - entry.topics.push_back(h256(topic)); - entry.data = fromHex(log.data, WhenError::Throw); - m_logs.push_back(entry); - } -} - -void ExecutionFramework::sendEther(Address const& _to, u256 const& _value) -{ - RPCSession::TransactionData d; - d.data = "0x"; - d.from = "0x" + toString(m_sender); - d.gas = toHex(m_gas, HexPrefix::Add); - d.gasPrice = toHex(m_gasPrice, HexPrefix::Add); - d.value = toHex(_value, HexPrefix::Add); - d.to = dev::toString(_to); - - string txHash = m_rpc.eth_sendTransaction(d); - m_rpc.test_mineBlocks(1); -} - -size_t ExecutionFramework::currentTimestamp() -{ - auto latestBlock = m_rpc.rpcCall("eth_getBlockByNumber", {"\"latest\"", "false"}); - return size_t(u256(latestBlock.get("timestamp", "invalid").asString())); -} - -Address ExecutionFramework::account(size_t _i) -{ - return Address(m_rpc.accountCreateIfNotExists(_i)); -} - -bool ExecutionFramework::addressHasCode(Address const& _addr) -{ - string code = m_rpc.eth_getCode(toString(_addr), "latest"); - return !code.empty() && code != "0x"; -} - -u256 ExecutionFramework::balanceAt(Address const& _addr) -{ - return u256(m_rpc.eth_getBalance(toString(_addr), "latest")); -} - -bool ExecutionFramework::storageEmpty(Address const& _addr) -{ - h256 root(m_rpc.eth_getStorageRoot(toString(_addr), "latest")); - BOOST_CHECK(root); - return root == EmptyTrie; } diff --git a/test/libsolidity/SolidityExecutionFramework.h b/test/libsolidity/SolidityExecutionFramework.h index 7d44edaf..03e3a881 100644 --- a/test/libsolidity/SolidityExecutionFramework.h +++ b/test/libsolidity/SolidityExecutionFramework.h @@ -1,18 +1,18 @@ /* - This file is part of cpp-ethereum. + This file is part of solidity. - cpp-ethereum is free software: you can redistribute it and/or modify + 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. - cpp-ethereum is distributed in the hope that it will be useful, + 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. + along with solidity. If not, see <http://www.gnu.org/licenses/>. */ /** * @author Christian <c@ethdev.com> @@ -24,12 +24,7 @@ #include <functional> -#include "../TestHelper.h" -#include "../RPCSession.h" - -#include <libdevcore/ABI.h> -#include <libdevcore/FixedHash.h> -#include <libevmasm/Instruction.h> +#include "../ExecutionFramework.h" #include <libsolidity/interface/CompilerStack.h> #include <libsolidity/interface/Exceptions.h> @@ -39,40 +34,29 @@ namespace dev { namespace solidity { - using rational = boost::rational<dev::bigint>; - /// An Ethereum address: 20 bytes. - /// @NOTE This is not endian-specific; it's just a bunch of bytes. - using Address = h160; - - // The various denominations; here for ease of use where needed within code. - static const u256 ether = exp10<18>(); - static const u256 finney = exp10<15>(); - static const u256 szabo = exp10<12>(); - static const u256 shannon = exp10<9>(); - static const u256 wei = exp10<0>(); namespace test { -class ExecutionFramework +class SolidityExecutionFramework: public dev::test::ExecutionFramework { public: - ExecutionFramework(); + SolidityExecutionFramework(); - bytes const& compileAndRunWithoutCheck( + virtual bytes const& compileAndRunWithoutCheck( std::string const& _sourceCode, u256 const& _value = 0, std::string const& _contractName = "", bytes const& _arguments = bytes(), - std::map<std::string, Address> const& _libraryAddresses = std::map<std::string, Address>() - ) + std::map<std::string, dev::test::Address> const& _libraryAddresses = std::map<std::string, dev::test::Address>() + ) override { // Silence compiler version warning std::string sourceCode = "pragma solidity >=0.0;\n" + _sourceCode; m_compiler.reset(false); m_compiler.addSource("", sourceCode); - if (!m_compiler.compile(m_optimize, m_optimizeRuns)) + if (!m_compiler.compile(m_optimize, m_optimizeRuns, _libraryAddresses)) { for (auto const& error: m_compiler.errors()) SourceReferenceFormatter::printExceptionInformation( @@ -84,230 +68,13 @@ public: BOOST_ERROR("Compiling contract failed"); } eth::LinkerObject obj = m_compiler.object(_contractName); - obj.link(_libraryAddresses); BOOST_REQUIRE(obj.linkReferences.empty()); sendMessage(obj.bytecode + _arguments, true, _value); return m_output; } - bytes const& compileAndRun( - std::string const& _sourceCode, - u256 const& _value = 0, - std::string const& _contractName = "", - bytes const& _arguments = bytes(), - std::map<std::string, Address> const& _libraryAddresses = std::map<std::string, Address>() - ) - { - compileAndRunWithoutCheck(_sourceCode, _value, _contractName, _arguments, _libraryAddresses); - BOOST_REQUIRE(!m_output.empty()); - return m_output; - } - - template <class... Args> - bytes const& callContractFunctionWithValue(std::string _sig, u256 const& _value, Args const&... _arguments) - { - FixedHash<4> hash(dev::keccak256(_sig)); - sendMessage(hash.asBytes() + encodeArgs(_arguments...), false, _value); - return m_output; - } - - template <class... Args> - bytes const& callContractFunction(std::string _sig, Args const&... _arguments) - { - return callContractFunctionWithValue(_sig, 0, _arguments...); - } - - template <class CppFunction, class... Args> - void testSolidityAgainstCpp(std::string _sig, CppFunction const& _cppFunction, Args const&... _arguments) - { - bytes solidityResult = callContractFunction(_sig, _arguments...); - bytes cppResult = callCppAndEncodeResult(_cppFunction, _arguments...); - BOOST_CHECK_MESSAGE( - solidityResult == cppResult, - "Computed values do not match.\nSolidity: " + - toHex(solidityResult) + - "\nC++: " + - toHex(cppResult) - ); - } - - template <class CppFunction, class... Args> - void testSolidityAgainstCppOnRange(std::string _sig, CppFunction const& _cppFunction, u256 const& _rangeStart, u256 const& _rangeEnd) - { - for (u256 argument = _rangeStart; argument < _rangeEnd; ++argument) - { - bytes solidityResult = callContractFunction(_sig, argument); - bytes cppResult = callCppAndEncodeResult(_cppFunction, argument); - BOOST_CHECK_MESSAGE( - solidityResult == cppResult, - "Computed values do not match.\nSolidity: " + - toHex(solidityResult) + - "\nC++: " + - toHex(cppResult) + - "\nArgument: " + - toHex(encode(argument)) - ); - } - } - - static bytes encode(bool _value) { return encode(byte(_value)); } - static bytes encode(int _value) { return encode(u256(_value)); } - static bytes encode(size_t _value) { return encode(u256(_value)); } - static bytes encode(char const* _value) { return encode(std::string(_value)); } - static bytes encode(byte _value) { return bytes(31, 0) + bytes{_value}; } - static bytes encode(u256 const& _value) { return toBigEndian(_value); } - /// @returns the fixed-point encoding of a rational number with a given - /// number of fractional bits. - static bytes encode(std::pair<rational, int> const& _valueAndPrecision) - { - rational const& value = _valueAndPrecision.first; - int fractionalBits = _valueAndPrecision.second; - return encode(u256((value.numerator() << fractionalBits) / value.denominator())); - } - static bytes encode(h256 const& _value) { return _value.asBytes(); } - static bytes encode(bytes const& _value, bool _padLeft = true) - { - bytes padding = bytes((32 - _value.size() % 32) % 32, 0); - return _padLeft ? padding + _value : _value + padding; - } - static bytes encode(std::string const& _value) { return encode(asBytes(_value), false); } - template <class _T> - static bytes encode(std::vector<_T> const& _value) - { - bytes ret; - for (auto const& v: _value) - ret += encode(v); - return ret; - } - - template <class FirstArg, class... Args> - static bytes encodeArgs(FirstArg const& _firstArg, Args const&... _followingArgs) - { - return encode(_firstArg) + encodeArgs(_followingArgs...); - } - static bytes encodeArgs() - { - return bytes(); - } - //@todo might be extended in the future - template <class Arg> - static bytes encodeDyn(Arg const& _arg) - { - return encodeArgs(u256(0x20), u256(_arg.size()), _arg); - } - class ContractInterface - { - public: - ContractInterface(ExecutionFramework& _framework): m_framework(_framework) {} - - void setNextValue(u256 const& _value) { m_nextValue = _value; } - - protected: - template <class... Args> - bytes const& call(std::string const& _sig, Args const&... _arguments) - { - auto const& ret = m_framework.callContractFunctionWithValue(_sig, m_nextValue, _arguments...); - m_nextValue = 0; - return ret; - } - - void callString(std::string const& _name, std::string const& _arg) - { - BOOST_CHECK(call(_name + "(string)", u256(0x20), _arg.length(), _arg).empty()); - } - - void callStringAddress(std::string const& _name, std::string const& _arg1, u160 const& _arg2) - { - BOOST_CHECK(call(_name + "(string,address)", u256(0x40), _arg2, _arg1.length(), _arg1).empty()); - } - - void callStringAddressBool(std::string const& _name, std::string const& _arg1, u160 const& _arg2, bool _arg3) - { - BOOST_CHECK(call(_name + "(string,address,bool)", u256(0x60), _arg2, _arg3, _arg1.length(), _arg1).empty()); - } - - void callStringBytes32(std::string const& _name, std::string const& _arg1, h256 const& _arg2) - { - BOOST_CHECK(call(_name + "(string,bytes32)", u256(0x40), _arg2, _arg1.length(), _arg1).empty()); - } - - u160 callStringReturnsAddress(std::string const& _name, std::string const& _arg) - { - bytes const& ret = call(_name + "(string)", u256(0x20), _arg.length(), _arg); - BOOST_REQUIRE(ret.size() == 0x20); - BOOST_CHECK(std::count(ret.begin(), ret.begin() + 12, 0) == 12); - return eth::abiOut<u160>(ret); - } - - std::string callAddressReturnsString(std::string const& _name, u160 const& _arg) - { - bytesConstRef ret = ref(call(_name + "(address)", _arg)); - BOOST_REQUIRE(ret.size() >= 0x20); - u256 offset = eth::abiOut<u256>(ret); - BOOST_REQUIRE_EQUAL(offset, 0x20); - u256 len = eth::abiOut<u256>(ret); - BOOST_REQUIRE_EQUAL(ret.size(), ((len + 0x1f) / 0x20) * 0x20); - return ret.cropped(0, size_t(len)).toString(); - } - - h256 callStringReturnsBytes32(std::string const& _name, std::string const& _arg) - { - bytes const& ret = call(_name + "(string)", u256(0x20), _arg.length(), _arg); - BOOST_REQUIRE(ret.size() == 0x20); - return eth::abiOut<h256>(ret); - } - - private: - u256 m_nextValue; - ExecutionFramework& m_framework; - }; - -private: - template <class CppFunction, class... Args> - auto callCppAndEncodeResult(CppFunction const& _cppFunction, Args const&... _arguments) - -> typename std::enable_if<std::is_void<decltype(_cppFunction(_arguments...))>::value, bytes>::type - { - _cppFunction(_arguments...); - return bytes(); - } - template <class CppFunction, class... Args> - auto callCppAndEncodeResult(CppFunction const& _cppFunction, Args const&... _arguments) - -> typename std::enable_if<!std::is_void<decltype(_cppFunction(_arguments...))>::value, bytes>::type - { - return encode(_cppFunction(_arguments...)); - } - protected: - void sendMessage(bytes const& _data, bool _isCreation, u256 const& _value = 0); - void sendEther(Address const& _to, u256 const& _value); - size_t currentTimestamp(); - - /// @returns the (potentially newly created) _ith address. - Address account(size_t _i); - - u256 balanceAt(Address const& _addr); - bool storageEmpty(Address const& _addr); - bool addressHasCode(Address const& _addr); - - RPCSession& m_rpc; - - struct LogEntry - { - Address address; - std::vector<h256> topics; - bytes data; - }; - - size_t m_optimizeRuns = 200; - bool m_optimize = false; dev::solidity::CompilerStack m_compiler; - Address m_sender; - Address m_contractAddress; - u256 const m_gasPrice = 100 * szabo; - u256 const m_gas = 100000000; - bytes m_output; - std::vector<LogEntry> m_logs; - u256 m_gasUsed; }; } diff --git a/test/libsolidity/SolidityExpressionCompiler.cpp b/test/libsolidity/SolidityExpressionCompiler.cpp index 91edfefd..0c5a09c3 100644 --- a/test/libsolidity/SolidityExpressionCompiler.cpp +++ b/test/libsolidity/SolidityExpressionCompiler.cpp @@ -1,18 +1,18 @@ /* - This file is part of cpp-ethereum. + This file is part of solidity. - cpp-ethereum is free software: you can redistribute it and/or modify + 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. - cpp-ethereum is distributed in the hope that it will be useful, + 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. + along with solidity. If not, see <http://www.gnu.org/licenses/>. */ /** * @author Christian <c@ethdev.com> @@ -168,9 +168,11 @@ BOOST_AUTO_TEST_SUITE(SolidityExpressionCompiler) BOOST_AUTO_TEST_CASE(literal_true) { - char const* sourceCode = "contract test {\n" - " function f() { var x = true; }" - "}\n"; + char const* sourceCode = R"( + contract test { + function f() { var x = true; } + } + )"; bytes code = compileFirstExpression(sourceCode); bytes expectation({byte(Instruction::PUSH1), 0x1}); @@ -179,9 +181,11 @@ BOOST_AUTO_TEST_CASE(literal_true) BOOST_AUTO_TEST_CASE(literal_false) { - char const* sourceCode = "contract test {\n" - " function f() { var x = false; }" - "}\n"; + char const* sourceCode = R"( + contract test { + function f() { var x = false; } + } + )"; bytes code = compileFirstExpression(sourceCode); bytes expectation({byte(Instruction::PUSH1), 0x0}); @@ -190,9 +194,11 @@ BOOST_AUTO_TEST_CASE(literal_false) BOOST_AUTO_TEST_CASE(int_literal) { - char const* sourceCode = "contract test {\n" - " function f() { var x = 0x12345678901234567890; }" - "}\n"; + char const* sourceCode = R"( + contract test { + function f() { var x = 0x12345678901234567890; } + } + )"; bytes code = compileFirstExpression(sourceCode); bytes expectation({byte(Instruction::PUSH10), 0x12, 0x34, 0x56, 0x78, 0x90, @@ -204,11 +210,11 @@ BOOST_AUTO_TEST_CASE(int_with_wei_ether_subdenomination) { char const* sourceCode = R"( contract test { - function test () - { + function test () { var x = 1 wei; } - })"; + } + )"; bytes code = compileFirstExpression(sourceCode); bytes expectation({byte(Instruction::PUSH1), 0x1}); @@ -219,11 +225,11 @@ BOOST_AUTO_TEST_CASE(int_with_szabo_ether_subdenomination) { char const* sourceCode = R"( contract test { - function test () - { + function test () { var x = 1 szabo; } - })"; + } + )"; bytes code = compileFirstExpression(sourceCode); bytes expectation({byte(Instruction::PUSH5), 0xe8, 0xd4, 0xa5, 0x10, 0x00}); @@ -249,11 +255,11 @@ BOOST_AUTO_TEST_CASE(int_with_ether_ether_subdenomination) { char const* sourceCode = R"( contract test { - function test () - { + function test () { var x = 1 ether; } - })"; + } + )"; bytes code = compileFirstExpression(sourceCode); bytes expectation({byte(Instruction::PUSH8), 0xd, 0xe0, 0xb6, 0xb3, 0xa7, 0x64, 0x00, 0x00}); @@ -262,9 +268,11 @@ BOOST_AUTO_TEST_CASE(int_with_ether_ether_subdenomination) BOOST_AUTO_TEST_CASE(comparison) { - char const* sourceCode = "contract test {\n" - " function f() { var x = (0x10aa < 0x11aa) != true; }" - "}\n"; + char const* sourceCode = R"( + contract test { + function f() { var x = (0x10aa < 0x11aa) != true; } + } + )"; bytes code = compileFirstExpression(sourceCode); bytes expectation({byte(Instruction::PUSH1), 0x1, byte(Instruction::ISZERO), byte(Instruction::ISZERO), @@ -278,9 +286,11 @@ BOOST_AUTO_TEST_CASE(comparison) BOOST_AUTO_TEST_CASE(short_circuiting) { - char const* sourceCode = "contract test {\n" - " function f() { var x = true != (4 <= 8 + 10 || 9 != 2); }" - "}\n"; + char const* sourceCode = R"( + contract test { + function f() { var x = true != (4 <= 8 + 10 || 9 != 2); } + } + )"; bytes code = compileFirstExpression(sourceCode); bytes expectation({byte(Instruction::PUSH1), 0x12, // 8 + 10 @@ -305,9 +315,11 @@ BOOST_AUTO_TEST_CASE(short_circuiting) BOOST_AUTO_TEST_CASE(arithmetics) { - char const* sourceCode = "contract test {\n" - " function f(uint y) { var x = ((((((((y ^ 8) & 7) | 6) - 5) + 4) % 3) / 2) * 1); }" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint y) { var x = ((((((((y ^ 8) & 7) | 6) - 5) + 4) % 3) / 2) * 1); } + } + )"; bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "y"}, {"test", "f", "x"}}); bytes expectation({byte(Instruction::PUSH1), 0x1, byte(Instruction::PUSH1), 0x2, @@ -339,9 +351,11 @@ BOOST_AUTO_TEST_CASE(arithmetics) BOOST_AUTO_TEST_CASE(unary_operators) { - char const* sourceCode = "contract test {\n" - " function f(int y) { var x = !(~+- y == 2); }" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(int y) { var x = !(~+- y == 2); } + } + )"; bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "y"}, {"test", "f", "x"}}); bytes expectation({byte(Instruction::PUSH1), 0x2, @@ -356,9 +370,11 @@ BOOST_AUTO_TEST_CASE(unary_operators) BOOST_AUTO_TEST_CASE(unary_inc_dec) { - char const* sourceCode = "contract test {\n" - " function f(uint a) { var x = --a ^ (a-- ^ (++a ^ a++)); }" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint a) { var x = --a ^ (a-- ^ (++a ^ a++)); } + } + )"; bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "a"}, {"test", "f", "x"}}); // Stack: a, x @@ -406,9 +422,11 @@ BOOST_AUTO_TEST_CASE(unary_inc_dec) BOOST_AUTO_TEST_CASE(assignment) { - char const* sourceCode = "contract test {\n" - " function f(uint a, uint b) { (a += b) * 2; }" - "}\n"; + char const* sourceCode = R"( + contract test { + function f(uint a, uint b) { (a += b) * 2; } + } + )"; bytes code = compileFirstExpression(sourceCode, {}, {{"test", "f", "a"}, {"test", "f", "b"}}); // Stack: a, b @@ -427,9 +445,11 @@ BOOST_AUTO_TEST_CASE(assignment) BOOST_AUTO_TEST_CASE(negative_literals_8bits) { - char const* sourceCode = "contract test {\n" - " function f() { int8 x = -0x80; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f() { int8 x = -0x80; } + } + )"; bytes code = compileFirstExpression(sourceCode); bytes expectation(bytes({byte(Instruction::PUSH32)}) + bytes(31, 0xff) + bytes(1, 0x80)); @@ -438,9 +458,11 @@ BOOST_AUTO_TEST_CASE(negative_literals_8bits) BOOST_AUTO_TEST_CASE(negative_literals_16bits) { - char const* sourceCode = "contract test {\n" - " function f() { int64 x = ~0xabc; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f() { int64 x = ~0xabc; } + } + )"; bytes code = compileFirstExpression(sourceCode); bytes expectation(bytes({byte(Instruction::PUSH32)}) + bytes(30, 0xff) + bytes{0xf5, 0x43}); @@ -451,9 +473,11 @@ BOOST_AUTO_TEST_CASE(intermediately_overflowing_literals) { // first literal itself is too large for 256 bits but it fits after all constant operations // have been applied - char const* sourceCode = "contract test {\n" - " function f() { var x = (0xffffffffffffffffffffffffffffffffffffffff * 0xffffffffffffffffffffffffff01) & 0xbf; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f() { var x = (0xffffffffffffffffffffffffffffffffffffffff * 0xffffffffffffffffffffffffff01) & 0xbf; } + } + )"; bytes code = compileFirstExpression(sourceCode); bytes expectation(bytes({byte(Instruction::PUSH1), 0xbf})); @@ -462,11 +486,13 @@ BOOST_AUTO_TEST_CASE(intermediately_overflowing_literals) BOOST_AUTO_TEST_CASE(blockhash) { - char const* sourceCode = "contract test {\n" - " function f() {\n" - " block.blockhash(3);\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function f() { + block.blockhash(3); + } + } + )"; bytes code = compileFirstExpression(sourceCode, {}, {}, {make_shared<MagicVariableDeclaration>("block", make_shared<MagicType>(MagicType::Kind::Block))}); diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 865eb7ce..576421fd 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -1,18 +1,18 @@ /* - This file is part of cpp-ethereum. + This file is part of solidity. - cpp-ethereum is free software: you can redistribute it and/or modify + 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. - cpp-ethereum is distributed in the hope that it will be useful, + 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. + along with solidity. If not, see <http://www.gnu.org/licenses/>. */ /** * @author Christian <c@ethdev.com> @@ -26,11 +26,13 @@ #include <libsolidity/parsing/Scanner.h> #include <libsolidity/parsing/Parser.h> #include <libsolidity/analysis/NameAndTypeResolver.h> +#include <libsolidity/analysis/StaticAnalyzer.h> #include <libsolidity/analysis/SyntaxChecker.h> #include <libsolidity/interface/Exceptions.h> #include <libsolidity/analysis/GlobalContext.h> #include <libsolidity/analysis/TypeChecker.h> #include "../TestHelper.h" +#include "ErrorCheck.h" using namespace std; @@ -44,8 +46,8 @@ namespace test namespace { -pair<ASTPointer<SourceUnit>, std::shared_ptr<Error::Type const>> -parseAnalyseAndReturnError(string const& _source, bool _reportWarnings = false, bool _insertVersionPragma = true) +pair<ASTPointer<SourceUnit>, std::shared_ptr<Error const>> +parseAnalyseAndReturnError(string const& _source, bool _reportWarnings = false, bool _insertVersionPragma = true, bool _allowMultipleErrors = false) { // Silence compiler version warning string source = _insertVersionPragma ? "pragma solidity >=0.0;\n" + _source : _source; @@ -61,7 +63,7 @@ parseAnalyseAndReturnError(string const& _source, bool _reportWarnings = false, SyntaxChecker syntaxChecker(errors); if (!syntaxChecker.checkSyntax(*sourceUnit)) - return make_pair(sourceUnit, std::make_shared<Error::Type const>(errors[0]->type())); + return make_pair(sourceUnit, errors.at(0)); std::shared_ptr<GlobalContext> globalContext = make_shared<GlobalContext>(); NameAndTypeResolver resolver(globalContext->declarations(), errors); @@ -88,15 +90,21 @@ parseAnalyseAndReturnError(string const& _source, bool _reportWarnings = false, TypeChecker typeChecker(errors); bool success = typeChecker.checkTypeRequirements(*contract); BOOST_CHECK(success || !errors.empty()); - } + if (success) + { + StaticAnalyzer staticAnalyzer(errors); + staticAnalyzer.analyze(*sourceUnit); + } + if (errors.size() > 1 && !_allowMultipleErrors) + BOOST_FAIL("Multiple errors found"); for (auto const& currentError: errors) { if ( (_reportWarnings && currentError->type() == Error::Type::Warning) || (!_reportWarnings && currentError->type() != Error::Type::Warning) ) - return make_pair(sourceUnit, std::make_shared<Error::Type const>(currentError->type())); + return make_pair(sourceUnit, currentError); } } catch (InternalCompilerError const& _e) @@ -108,7 +116,7 @@ parseAnalyseAndReturnError(string const& _source, bool _reportWarnings = false, } catch (Error const& _e) { - return make_pair(sourceUnit, std::make_shared<Error::Type const>(_e.type())); + return make_pair(sourceUnit, std::make_shared<Error const>(_e)); } catch (...) { @@ -130,9 +138,9 @@ bool success(string const& _source) return !parseAnalyseAndReturnError(_source).second; } -Error::Type expectError(std::string const& _source, bool _warning = false) +Error expectError(std::string const& _source, bool _warning = false, bool _allowMultiple = false) { - auto sourceAndError = parseAnalyseAndReturnError(_source, _warning); + auto sourceAndError = parseAnalyseAndReturnError(_source, _warning, true, _allowMultiple); BOOST_REQUIRE(!!sourceAndError.second); BOOST_REQUIRE(!!sourceAndError.first); return *sourceAndError.second; @@ -150,113 +158,173 @@ static ContractDefinition const* retrieveContract(ASTPointer<SourceUnit> _source } static FunctionTypePointer retrieveFunctionBySignature( - ContractDefinition const* _contract, + ContractDefinition const& _contract, std::string const& _signature ) { FixedHash<4> hash(dev::keccak256(_signature)); - return _contract->interfaceFunctions()[hash]; + return _contract.interfaceFunctions()[hash]; } } +#define CHECK_ERROR_OR_WARNING(text, typ, substring, warning, allowMulti) \ +do \ +{ \ + Error err = expectError((text), (warning), (allowMulti)); \ + BOOST_CHECK(err.type() == (Error::Type::typ)); \ + BOOST_CHECK(searchErrorMessage(err, (substring))); \ +} while(0) + +// [checkError(text, type, substring)] asserts that the compilation down to typechecking +// emits an error of type [type] and with a message containing [substring]. +#define CHECK_ERROR(text, type, substring) \ +CHECK_ERROR_OR_WARNING(text, type, substring, false, false) + +// [checkError(text, type, substring)] asserts that the compilation down to typechecking +// emits an error of type [type] and with a message containing [substring]. +#define CHECK_ERROR_ALLOW_MULTI(text, type, substring) \ +CHECK_ERROR_OR_WARNING(text, type, substring, false, true) + +// [checkWarning(text, type, substring)] asserts that the compilation down to typechecking +// emits a warning of type [type] and with a message containing [substring]. +#define CHECK_WARNING(text, substring) \ +CHECK_ERROR_OR_WARNING(text, Warning, substring, true, false) + +// [checkSuccess(text)] asserts that the compilation down to typechecking succeeds. +#define CHECK_SUCCESS(text) do { BOOST_CHECK(success((text))); } while(0) + +#define CHECK_SUCCESS_NO_WARNINGS(text) \ +do \ +{ \ + auto sourceAndError = parseAnalyseAndReturnError((text), true); \ + BOOST_CHECK(sourceAndError.second == nullptr); \ +} \ +while(0) + + BOOST_AUTO_TEST_SUITE(SolidityNameAndTypeResolution) BOOST_AUTO_TEST_CASE(smoke_test) { - char const* text = "contract test {\n" - " uint256 stateVariable1;\n" - " function fun(uint256 arg1) { uint256 y; }" - "}\n"; - BOOST_CHECK(success(text)); + char const* text = R"( + contract test { + uint256 stateVariable1; + function fun(uint256 arg1) { uint256 y; } + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(double_stateVariable_declaration) { - char const* text = "contract test {\n" - " uint256 variable;\n" - " uint128 variable;\n" - "}\n"; - BOOST_CHECK(expectError(text) == Error::Type::DeclarationError); + char const* text = R"( + contract test { + uint256 variable; + uint128 variable; + } + )"; + CHECK_ERROR(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(double_function_declaration) { - char const* text = "contract test {\n" - " function fun() { uint x; }\n" - " function fun() { uint x; }\n" - "}\n"; - BOOST_CHECK(expectError(text) == Error::Type::DeclarationError); + char const* text = R"( + contract test { + function fun() { uint x; } + function fun() { uint x; } + } + )"; + CHECK_ERROR(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(double_variable_declaration) { - char const* text = "contract test {\n" - " function f() { uint256 x; if (true) { uint256 x; } }\n" - "}\n"; - BOOST_CHECK(expectError(text) == Error::Type::DeclarationError); + char const* text = R"( + contract test { + function f() { + uint256 x; + if (true) { uint256 x; } + } + } + )"; + CHECK_ERROR(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(name_shadowing) { - char const* text = "contract test {\n" - " uint256 variable;\n" - " function f() { uint32 variable ; }" - "}\n"; - BOOST_CHECK(success(text)); + char const* text = R"( + contract test { + uint256 variable; + function f() { uint32 variable; } + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(name_references) { - char const* text = "contract test {\n" - " uint256 variable;\n" - " function f(uint256 arg) returns (uint out) { f(variable); test; out; }" - "}\n"; - BOOST_CHECK(success(text)); + char const* text = R"( + contract test { + uint256 variable; + function f(uint256 arg) returns (uint out) { f(variable); test; out; } + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(undeclared_name) { - char const* text = "contract test {\n" - " uint256 variable;\n" - " function f(uint256 arg) { f(notfound); }" - "}\n"; - BOOST_CHECK(expectError(text) == Error::Type::DeclarationError); + char const* text = R"( + contract test { + uint256 variable; + function f(uint256 arg) { + f(notfound); + } + } + )"; + CHECK_ERROR(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(reference_to_later_declaration) { - char const* text = "contract test {\n" - " function g() { f(); }" - " function f() { }" - "}\n"; - BOOST_CHECK(success(text)); + char const* text = R"( + contract test { + function g() { f(); } + function f() {} + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(struct_definition_directly_recursive) { - char const* text = "contract test {\n" - " struct MyStructName {\n" - " address addr;\n" - " MyStructName x;\n" - " }\n" - "}\n"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + char const* text = R"( + contract test { + struct MyStructName { + address addr; + MyStructName x; + } + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(struct_definition_indirectly_recursive) { - char const* text = "contract test {\n" - " struct MyStructName1 {\n" - " address addr;\n" - " uint256 count;\n" - " MyStructName2 x;\n" - " }\n" - " struct MyStructName2 {\n" - " MyStructName1 x;\n" - " }\n" - "}\n"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + char const* text = R"( + contract test { + struct MyStructName1 { + address addr; + uint256 count; + MyStructName2 x; + } + struct MyStructName2 { + MyStructName1 x; + } + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(struct_definition_not_really_recursive) @@ -267,184 +335,221 @@ BOOST_AUTO_TEST_CASE(struct_definition_not_really_recursive) struct s2 { s1 x; s1 y; } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(struct_definition_recursion_via_mapping) { - char const* text = "contract test {\n" - " struct MyStructName1 {\n" - " address addr;\n" - " uint256 count;\n" - " mapping(uint => MyStructName1) x;\n" - " }\n" - "}\n"; - BOOST_CHECK(success(text)); + char const* text = R"( + contract test { + struct MyStructName1 { + address addr; + uint256 count; + mapping(uint => MyStructName1) x; + } + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(type_inference_smoke_test) { - char const* text = "contract test {\n" - " function f(uint256 arg1, uint32 arg2) returns (bool ret) { var x = arg1 + arg2 == 8; ret = x; }" - "}\n"; - BOOST_CHECK(success(text)); + char const* text = R"( + contract test { + function f(uint256 arg1, uint32 arg2) returns (bool ret) { + var x = arg1 + arg2 == 8; ret = x; + } + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(type_checking_return) { - char const* text = "contract test {\n" - " function f() returns (bool r) { return 1 >= 2; }" - "}\n"; - BOOST_CHECK(success(text)); + char const* text = R"( + contract test { + function f() returns (bool r) { return 1 >= 2; } + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(type_checking_return_wrong_number) { - char const* text = "contract test {\n" - " function f() returns (bool r1, bool r2) { return 1 >= 2; }" - "}\n"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + char const* text = R"( + contract test { + function f() returns (bool r1, bool r2) { return 1 >= 2; } + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(type_checking_return_wrong_type) { - char const* text = "contract test {\n" - " function f() returns (uint256 r) { return 1 >= 2; }" - "}\n"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + char const* text = R"( + contract test { + function f() returns (uint256 r) { return 1 >= 2; } + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(type_checking_function_call) { - char const* text = "contract test {\n" - " function f() returns (bool r) { return g(12, true) == 3; }\n" - " function g(uint256 a, bool b) returns (uint256 r) { }\n" - "}\n"; - BOOST_CHECK(success(text)); + char const* text = R"( + contract test { + function f() returns (bool r) { return g(12, true) == 3; } + function g(uint256 a, bool b) returns (uint256 r) { } + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(type_conversion_for_comparison) { - char const* text = "contract test {\n" - " function f() { uint32(2) == int64(2); }" - "}\n"; - BOOST_CHECK(success(text)); + char const* text = R"( + contract test { + function f() { uint32(2) == int64(2); } + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(type_conversion_for_comparison_invalid) { - char const* text = "contract test {\n" - " function f() { int32(2) == uint64(2); }" - "}\n"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + char const* text = R"( + contract test { + function f() { int32(2) == uint64(2); } + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(type_inference_explicit_conversion) { - char const* text = "contract test {\n" - " function f() returns (int256 r) { var x = int256(uint32(2)); return x; }" - "}\n"; - BOOST_CHECK(success(text)); + char const* text = R"( + contract test { + function f() returns (int256 r) { var x = int256(uint32(2)); return x; } + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(large_string_literal) { - char const* text = "contract test {\n" - " function f() { var x = \"123456789012345678901234567890123\"; }" - "}\n"; - BOOST_CHECK(success(text)); + char const* text = R"( + contract test { + function f() { var x = "123456789012345678901234567890123"; } + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(balance) { - char const* text = "contract test {\n" - " function fun() {\n" - " uint256 x = address(0).balance;\n" - " }\n" - "}\n"; - BOOST_CHECK(success(text)); + char const* text = R"( + contract test { + function fun() { + uint256 x = address(0).balance; + } + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(balance_invalid) { - char const* text = "contract test {\n" - " function fun() {\n" - " address(0).balance = 7;\n" - " }\n" - "}\n"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + char const* text = R"( + contract test { + function fun() { + address(0).balance = 7; + } + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(assignment_to_mapping) { - char const* text = "contract test {\n" - " struct str {\n" - " mapping(uint=>uint) map;\n" - " }\n" - " str data;" - " function fun() {\n" - " var a = data.map;\n" - " data.map = a;\n" - " }\n" - "}\n"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + char const* text = R"( + contract test { + struct str { + mapping(uint=>uint) map; + } + str data; + function fun() { + var a = data.map; + data.map = a; + } + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(assignment_to_struct) { - char const* text = "contract test {\n" - " struct str {\n" - " mapping(uint=>uint) map;\n" - " }\n" - " str data;" - " function fun() {\n" - " var a = data;\n" - " data = a;\n" - " }\n" - "}\n"; - BOOST_CHECK(success(text)); + char const* text = R"( + contract test { + struct str { + mapping(uint=>uint) map; + } + str data; + function fun() { + var a = data; + data = a; + } + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(returns_in_constructor) { - char const* text = "contract test {\n" - " function test() returns (uint a) {\n" - " }\n" - "}\n"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + char const* text = R"( + contract test { + function test() returns (uint a) { } + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(forward_function_reference) { - char const* text = "contract First {\n" - " function fun() returns (bool ret) {\n" - " return Second(1).fun(1, true, 3) > 0;\n" - " }\n" - "}\n" - "contract Second {\n" - " function fun(uint a, bool b, uint c) returns (uint ret) {\n" - " if (First(2).fun() == true) return 1;\n" - " }\n" - "}\n"; - BOOST_CHECK(success(text)); + char const* text = R"( + contract First { + function fun() returns (bool ret) { + return Second(1).fun(1, true, 3) > 0; + } + } + contract Second { + function fun(uint a, bool b, uint c) returns (uint ret) { + if (First(2).fun() == true) return 1; + } + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(comparison_bitop_precedence) { - char const* text = "contract First {\n" - " function fun() returns (bool ret) {\n" - " return 1 & 2 == 8 & 9 && 1 ^ 2 < 4 | 6;\n" - " }\n" - "}\n"; - BOOST_CHECK(success(text)); + char const* text = R"( + contract First { + function fun() returns (bool ret) { + return 1 & 2 == 8 & 9 && 1 ^ 2 < 4 | 6; + } + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(function_no_implementation) { ASTPointer<SourceUnit> sourceUnit; - char const* text = "contract test {\n" - " function functionName(bytes32 input) returns (bytes32 out);\n" - "}\n"; + char const* text = R"( + contract test { + function functionName(bytes32 input) returns (bytes32 out); + } + )"; ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name Resolving failed"); std::vector<ASTPointer<ASTNode>> nodes = sourceUnit->nodes(); ContractDefinition* contract = dynamic_cast<ContractDefinition*>(nodes[1].get()); @@ -459,7 +564,7 @@ BOOST_AUTO_TEST_CASE(abstract_contract) char const* text = R"( contract base { function foo(); } contract derived is base { function foo() {} } - )"; + )"; ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name Resolving failed"); std::vector<ASTPointer<ASTNode>> nodes = sourceUnit->nodes(); ContractDefinition* base = dynamic_cast<ContractDefinition*>(nodes[1].get()); @@ -478,7 +583,7 @@ BOOST_AUTO_TEST_CASE(abstract_contract_with_overload) char const* text = R"( contract base { function foo(bool); } contract derived is base { function foo(uint) {} } - )"; + )"; ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name Resolving failed"); std::vector<ASTPointer<ASTNode>> nodes = sourceUnit->nodes(); ContractDefinition* base = dynamic_cast<ContractDefinition*>(nodes[1].get()); @@ -496,10 +601,10 @@ BOOST_AUTO_TEST_CASE(create_abstract_contract) contract base { function foo(); } contract derived { base b; - function foo() { b = new base();} - } - )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + function foo() { b = new base(); } + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(abstract_contract_constructor_args_optional) @@ -512,7 +617,7 @@ BOOST_AUTO_TEST_CASE(abstract_contract_constructor_args_optional) function derived(uint i) BaseBase(i){} function foo() {} } - )"; + )"; ETH_TEST_REQUIRE_NO_THROW(parseAndAnalyse(text), "Parsing and name resolving failed"); } @@ -526,7 +631,7 @@ BOOST_AUTO_TEST_CASE(abstract_contract_constructor_args_not_provided) function derived(uint 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); @@ -542,8 +647,8 @@ BOOST_AUTO_TEST_CASE(redeclare_implemented_abstract_function_as_abstract) contract base { function foo(); } contract derived is base { function foo() {} } contract wrong is derived { function foo(); } - )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(implement_abstract_via_constructor) @@ -564,11 +669,13 @@ BOOST_AUTO_TEST_CASE(implement_abstract_via_constructor) BOOST_AUTO_TEST_CASE(function_canonical_signature) { ASTPointer<SourceUnit> sourceUnit; - char const* text = "contract Test {\n" - " function foo(uint256 arg1, uint64 arg2, bool arg3) returns (uint256 ret) {\n" - " ret = arg1 + arg2;\n" - " }\n" - "}\n"; + char const* text = R"( + contract Test { + function foo(uint256 arg1, uint64 arg2, bool arg3) returns (uint256 ret) { + ret = arg1 + arg2; + } + } + )"; ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name Resolving failed"); for (ASTPointer<ASTNode> const& node: sourceUnit->nodes()) if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get())) @@ -581,11 +688,13 @@ BOOST_AUTO_TEST_CASE(function_canonical_signature) BOOST_AUTO_TEST_CASE(function_canonical_signature_type_aliases) { ASTPointer<SourceUnit> sourceUnit; - char const* text = "contract Test {\n" - " function boo(uint arg1, bytes32 arg2, address arg3) returns (uint ret) {\n" - " ret = 5;\n" - " }\n" - "}\n"; + char const* text = R"( + contract Test { + function boo(uint arg1, bytes32 arg2, address arg3) returns (uint ret) { + ret = 5; + } + } + )"; ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name Resolving failed"); for (ASTPointer<ASTNode> const& node: sourceUnit->nodes()) if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get())) @@ -606,9 +715,10 @@ BOOST_AUTO_TEST_CASE(function_external_types) } contract Test { function boo(uint arg2, bool arg3, bytes8 arg4, bool[2] pairs, uint[] dynamic, C carg, address[] addresses) external returns (uint ret) { - ret = 5; + ret = 5; } - })"; + } + )"; ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name Resolving failed"); for (ASTPointer<ASTNode> const& node: sourceUnit->nodes()) if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get())) @@ -630,7 +740,8 @@ BOOST_AUTO_TEST_CASE(enum_external_type) function boo(ActionChoices enumArg) external returns (uint ret) { ret = 5; } - })"; + } + )"; ETH_TEST_REQUIRE_NO_THROW(sourceUnit = parseAndAnalyse(text), "Parsing and name Resolving failed"); for (ASTPointer<ASTNode> const& node: sourceUnit->nodes()) if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get())) @@ -647,13 +758,14 @@ BOOST_AUTO_TEST_CASE(function_external_call_allowed_conversion) char const* text = R"( contract C {} contract Test { - function externalCall() { + function externalCall() { C arg; this.g(arg); } function g (C c) external {} - })"; - BOOST_CHECK(success(text)); + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(function_external_call_not_allowed_conversion) @@ -661,13 +773,14 @@ BOOST_AUTO_TEST_CASE(function_external_call_not_allowed_conversion) char const* text = R"( contract C {} contract Test { - function externalCall() { + function externalCall() { address arg; this.g(arg); } function g (C c) external {} - })"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(function_internal_allowed_conversion) @@ -682,8 +795,9 @@ BOOST_AUTO_TEST_CASE(function_internal_allowed_conversion) function internalCall() { g(a); } - })"; - BOOST_CHECK(success(text)); + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(function_internal_not_allowed_conversion) @@ -698,19 +812,20 @@ BOOST_AUTO_TEST_CASE(function_internal_not_allowed_conversion) function internalCall() { g(a); } - })"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(hash_collision_in_interface) { - char const* text = "contract test {\n" - " function gsf() {\n" - " }\n" - " function tgeo() {\n" - " }\n" - "}\n"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + char const* text = R"( + contract test { + function gsf() { } + function tgeo() { } + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(inheritance_basic) @@ -722,7 +837,7 @@ BOOST_AUTO_TEST_CASE(inheritance_basic) function f() { baseMember = 7; } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(inheritance_diamond_basic) @@ -735,7 +850,7 @@ BOOST_AUTO_TEST_CASE(inheritance_diamond_basic) function g() { f(); rootFunction(); } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(cyclic_inheritance) @@ -744,7 +859,7 @@ BOOST_AUTO_TEST_CASE(cyclic_inheritance) contract A is B { } contract B is A { } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR_ALLOW_MULTI(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(legal_override_direct) @@ -753,7 +868,7 @@ BOOST_AUTO_TEST_CASE(legal_override_direct) contract B { function f() {} } contract C is B { function f(uint i) {} } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(legal_override_indirect) @@ -763,7 +878,7 @@ BOOST_AUTO_TEST_CASE(legal_override_indirect) contract B { function f() {} } contract C is A, B { } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(illegal_override_visibility) @@ -772,7 +887,7 @@ BOOST_AUTO_TEST_CASE(illegal_override_visibility) contract B { function f() internal {} } contract C is B { function f() public {} } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(illegal_override_constness) @@ -781,7 +896,7 @@ BOOST_AUTO_TEST_CASE(illegal_override_constness) contract B { function f() constant {} } contract C is B { function f() {} } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(complex_inheritance) @@ -791,7 +906,7 @@ BOOST_AUTO_TEST_CASE(complex_inheritance) contract B { function f() {} function g() returns (uint8 r) {} } contract C is A, B { } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(constructor_visibility) @@ -801,7 +916,7 @@ BOOST_AUTO_TEST_CASE(constructor_visibility) contract A { function A() { } } contract B is A { function f() { A x = A(0); } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(overriding_constructor) @@ -811,7 +926,7 @@ BOOST_AUTO_TEST_CASE(overriding_constructor) contract A { function A() { } } contract B is A { function A() returns (uint8 r) {} } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(missing_base_constructor_arguments) @@ -820,7 +935,7 @@ BOOST_AUTO_TEST_CASE(missing_base_constructor_arguments) contract A { function A(uint a) { } } contract B is A { } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(base_constructor_arguments_override) @@ -829,7 +944,7 @@ BOOST_AUTO_TEST_CASE(base_constructor_arguments_override) contract A { function A(uint a) { } } contract B is A { } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(implicit_derived_to_base_conversion) @@ -840,7 +955,7 @@ BOOST_AUTO_TEST_CASE(implicit_derived_to_base_conversion) function f() { A a = B(1); } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(implicit_base_to_derived_conversion) @@ -851,7 +966,7 @@ BOOST_AUTO_TEST_CASE(implicit_base_to_derived_conversion) function f() { B b = A(1); } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(super_excludes_current_contract) @@ -868,7 +983,7 @@ BOOST_AUTO_TEST_CASE(super_excludes_current_contract) } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(function_modifier_invocation) @@ -880,7 +995,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_invocation) modifier mod2(bytes7 a) { while (a == "1234567") _; } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(invalid_function_modifier_type) @@ -891,7 +1006,7 @@ BOOST_AUTO_TEST_CASE(invalid_function_modifier_type) modifier mod1(uint a) { if (a > 0) _; } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(function_modifier_invocation_parameters) @@ -903,7 +1018,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_invocation_parameters) modifier mod2(bytes7 a) { while (a == "1234567") _; } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(function_modifier_invocation_local_variables) @@ -914,7 +1029,7 @@ BOOST_AUTO_TEST_CASE(function_modifier_invocation_local_variables) modifier mod(uint a) { if (a > 0) _; } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(legal_modifier_override) @@ -923,7 +1038,7 @@ BOOST_AUTO_TEST_CASE(legal_modifier_override) contract A { modifier mod(uint a) { _; } } contract B is A { modifier mod(uint a) { _; } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(illegal_modifier_override) @@ -932,7 +1047,7 @@ BOOST_AUTO_TEST_CASE(illegal_modifier_override) contract A { modifier mod(uint a) { _; } } contract B is A { modifier mod(uint8 a) { _; } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(modifier_overrides_function) @@ -941,7 +1056,7 @@ BOOST_AUTO_TEST_CASE(modifier_overrides_function) contract A { modifier mod(uint a) { _; } } contract B is A { function mod(uint a) { } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(function_overrides_modifier) @@ -950,7 +1065,7 @@ BOOST_AUTO_TEST_CASE(function_overrides_modifier) contract A { function mod(uint a) { } } contract B is A { modifier mod(uint a) { _; } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(modifier_returns_value) @@ -961,31 +1076,33 @@ BOOST_AUTO_TEST_CASE(modifier_returns_value) modifier mod(uint a) { _; return 7; } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(state_variable_accessors) { - char const* text = "contract test {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "uint256 public foo;\n" - "mapping(uint=>bytes4) public map;\n" - "mapping(uint=>mapping(uint=>bytes4)) public multiple_map;\n" - "}\n"; + char const* text = R"( + contract test { + function fun() { + uint64(2); + } + uint256 public foo; + mapping(uint=>bytes4) public map; + mapping(uint=>mapping(uint=>bytes4)) public multiple_map; + } + )"; ASTPointer<SourceUnit> source; ContractDefinition const* contract; ETH_TEST_CHECK_NO_THROW(source = parseAndAnalyse(text), "Parsing and Resolving names failed"); BOOST_REQUIRE((contract = retrieveContract(source, 0)) != nullptr); - FunctionTypePointer function = retrieveFunctionBySignature(contract, "foo()"); + FunctionTypePointer function = retrieveFunctionBySignature(*contract, "foo()"); BOOST_REQUIRE(function && function->hasDeclaration()); auto returnParams = function->returnParameterTypeNames(false); BOOST_CHECK_EQUAL(returnParams.at(0), "uint256"); BOOST_CHECK(function->isConstant()); - function = retrieveFunctionBySignature(contract, "map(uint256)"); + function = retrieveFunctionBySignature(*contract, "map(uint256)"); BOOST_REQUIRE(function && function->hasDeclaration()); auto params = function->parameterTypeNames(false); BOOST_CHECK_EQUAL(params.at(0), "uint256"); @@ -993,7 +1110,7 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors) BOOST_CHECK_EQUAL(returnParams.at(0), "bytes4"); BOOST_CHECK(function->isConstant()); - function = retrieveFunctionBySignature(contract, "multiple_map(uint256,uint256)"); + function = retrieveFunctionBySignature(*contract, "multiple_map(uint256,uint256)"); BOOST_REQUIRE(function && function->hasDeclaration()); params = function->parameterTypeNames(false); BOOST_CHECK_EQUAL(params.at(0), "uint256"); @@ -1005,34 +1122,38 @@ BOOST_AUTO_TEST_CASE(state_variable_accessors) BOOST_AUTO_TEST_CASE(function_clash_with_state_variable_accessor) { - char const* text = "contract test {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "uint256 foo;\n" - " function foo() {}\n" - "}\n"; - BOOST_CHECK(expectError(text) == Error::Type::DeclarationError); + char const* text = R"( + contract test { + function fun() { + uint64(2); + } + uint256 foo; + function foo() {} + } + )"; + CHECK_ERROR(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(private_state_variable) { - char const* text = "contract test {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "uint256 private foo;\n" - "uint256 internal bar;\n" - "}\n"; + char const* text = R"( + contract test { + function fun() { + uint64(2); + } + uint256 private foo; + uint256 internal bar; + } + )"; ASTPointer<SourceUnit> source; ContractDefinition const* contract; ETH_TEST_CHECK_NO_THROW(source = parseAndAnalyse(text), "Parsing and Resolving names failed"); BOOST_CHECK((contract = retrieveContract(source, 0)) != nullptr); FunctionTypePointer function; - function = retrieveFunctionBySignature(contract, "foo()"); + function = retrieveFunctionBySignature(*contract, "foo()"); BOOST_CHECK_MESSAGE(function == nullptr, "Accessor function of a private variable should not exist"); - function = retrieveFunctionBySignature(contract, "bar()"); + function = retrieveFunctionBySignature(*contract, "bar()"); BOOST_CHECK_MESSAGE(function == nullptr, "Accessor function of an internal variable should not exist"); } @@ -1045,71 +1166,79 @@ BOOST_AUTO_TEST_CASE(missing_state_variable) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(base_class_state_variable_accessor) { // test for issue #1126 https://github.com/ethereum/cpp-ethereum/issues/1126 - char const* text = "contract Parent {\n" - " uint256 public m_aMember;\n" - "}\n" - "contract Child is Parent{\n" - " function foo() returns (uint256) { return Parent.m_aMember; }\n" - "}\n"; - BOOST_CHECK(success(text)); + char const* text = R"( + contract Parent { + uint256 public m_aMember; + } + contract Child is Parent { + function foo() returns (uint256) { return Parent.m_aMember; } + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(struct_accessor_one_array_only) { char const* sourceCode = R"( contract test { - struct Data { uint[15] m_array; } + struct Data { uint[15] m_array; } Data public data; } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(base_class_state_variable_internal_member) { - char const* text = "contract Parent {\n" - " uint256 internal m_aMember;\n" - "}\n" - "contract Child is Parent{\n" - " function foo() returns (uint256) { return Parent.m_aMember; }\n" - "}\n"; - BOOST_CHECK(success(text)); + char const* text = R"( + contract Parent { + uint256 internal m_aMember; + } + contract Child is Parent{ + function foo() returns (uint256) { return Parent.m_aMember; } + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(state_variable_member_of_wrong_class1) { - char const* text = "contract Parent1 {\n" - " uint256 internal m_aMember1;\n" - "}\n" - "contract Parent2 is Parent1{\n" - " uint256 internal m_aMember2;\n" - "}\n" - "contract Child is Parent2{\n" - " function foo() returns (uint256) { return Parent2.m_aMember1; }\n" - "}\n"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + char const* text = R"( + contract Parent1 { + uint256 internal m_aMember1; + } + contract Parent2 is Parent1{ + uint256 internal m_aMember2; + } + contract Child is Parent2{ + function foo() returns (uint256) { return Parent2.m_aMember1; } + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(state_variable_member_of_wrong_class2) { - char const* text = "contract Parent1 {\n" - " uint256 internal m_aMember1;\n" - "}\n" - "contract Parent2 is Parent1{\n" - " uint256 internal m_aMember2;\n" - "}\n" - "contract Child is Parent2{\n" - " function foo() returns (uint256) { return Child.m_aMember2; }\n" - " uint256 public m_aMember3;\n" - "}\n"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + char const* text = R"( + contract Parent1 { + uint256 internal m_aMember1; + } + contract Parent2 is Parent1 { + uint256 internal m_aMember2; + } + contract Child is Parent2 { + function foo() returns (uint256) { return Child.m_aMember2; } + uint256 public m_aMember3; + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(fallback_function) @@ -1120,7 +1249,7 @@ BOOST_AUTO_TEST_CASE(fallback_function) function() { x = 2; } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(fallback_function_with_arguments) @@ -1131,7 +1260,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_with_arguments) function(uint a) { x = 2; } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(fallback_function_in_library) @@ -1141,7 +1270,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_in_library) function() {} } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(fallback_function_with_return_parameters) @@ -1151,7 +1280,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_with_return_parameters) function() returns (uint) { } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(fallback_function_with_constant_modifier) @@ -1162,7 +1291,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_with_constant_modifier) function() constant { x = 2; } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(fallback_function_twice) @@ -1174,7 +1303,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_twice) function() { x = 3; } } )"; - BOOST_CHECK(expectError(text) == Error::Type::DeclarationError); + CHECK_ERROR_ALLOW_MULTI(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(fallback_function_inheritance) @@ -1188,7 +1317,7 @@ BOOST_AUTO_TEST_CASE(fallback_function_inheritance) function() { x = 2; } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(event) @@ -1197,8 +1326,9 @@ BOOST_AUTO_TEST_CASE(event) contract c { event e(uint indexed a, bytes3 indexed s, bool indexed b); function f() { e(2, "abc", true); } - })"; - BOOST_CHECK(success(text)); + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(event_too_many_indexed) @@ -1206,8 +1336,9 @@ BOOST_AUTO_TEST_CASE(event_too_many_indexed) char const* text = R"( contract c { event e(uint indexed a, bytes3 indexed b, bool indexed c, uint indexed d); - })"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(anonymous_event_four_indexed) @@ -1215,8 +1346,9 @@ BOOST_AUTO_TEST_CASE(anonymous_event_four_indexed) char const* text = R"( contract c { event e(uint indexed a, bytes3 indexed b, bool indexed c, uint indexed d) anonymous; - })"; - BOOST_CHECK(success(text)); + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(anonymous_event_too_many_indexed) @@ -1224,8 +1356,9 @@ BOOST_AUTO_TEST_CASE(anonymous_event_too_many_indexed) char const* text = R"( contract c { event e(uint indexed a, bytes3 indexed b, bool indexed c, uint indexed d, uint indexed e) anonymous; - })"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(event_call) @@ -1234,8 +1367,9 @@ BOOST_AUTO_TEST_CASE(event_call) contract c { event e(uint a, bytes3 indexed s, bool indexed b); function f() { e(2, "abc", true); } - })"; - BOOST_CHECK(success(text)); + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(event_inheritance) @@ -1246,8 +1380,9 @@ BOOST_AUTO_TEST_CASE(event_inheritance) } contract c is base { function f() { e(2, "abc", true); } - })"; - BOOST_CHECK(success(text)); + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(multiple_events_argument_clash) @@ -1256,8 +1391,9 @@ BOOST_AUTO_TEST_CASE(multiple_events_argument_clash) contract c { event e1(uint a, uint e1, uint e2); event e2(uint a, uint e1, uint e2); - })"; - BOOST_CHECK(success(text)); + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(access_to_default_function_visibility) @@ -1268,8 +1404,9 @@ BOOST_AUTO_TEST_CASE(access_to_default_function_visibility) } contract d { function g() { c(0).f(); } - })"; - BOOST_CHECK(success(text)); + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(access_to_internal_function) @@ -1280,8 +1417,9 @@ BOOST_AUTO_TEST_CASE(access_to_internal_function) } contract d { function g() { c(0).f(); } - })"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(access_to_default_state_variable_visibility) @@ -1292,8 +1430,9 @@ BOOST_AUTO_TEST_CASE(access_to_default_state_variable_visibility) } contract d { function g() { c(0).a(); } - })"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(access_to_internal_state_variable) @@ -1304,115 +1443,146 @@ BOOST_AUTO_TEST_CASE(access_to_internal_state_variable) } contract d { function g() { c(0).a(); } - })"; - BOOST_CHECK(success(text)); + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(error_count_in_named_args) { - char const* sourceCode = "contract test {\n" - " function a(uint a, uint b) returns (uint r) { r = a + b; }\n" - " function b() returns (uint r) { r = a({a: 1}); }\n" - "}\n"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + char const* sourceCode = R"( + contract test { + function a(uint a, uint b) returns (uint r) { + r = a + b; + } + function b() returns (uint r) { + r = a({a: 1}); + } + } + )"; + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(empty_in_named_args) { - char const* sourceCode = "contract test {\n" - " function a(uint a, uint b) returns (uint r) { r = a + b; }\n" - " function b() returns (uint r) { r = a({}); }\n" - "}\n"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + char const* sourceCode = R"( + contract test { + function a(uint a, uint b) returns (uint r) { + r = a + b; + } + function b() returns (uint r) { + r = a({}); + } + } + )"; + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(duplicate_parameter_names_in_named_args) { - char const* sourceCode = "contract test {\n" - " function a(uint a, uint b) returns (uint r) { r = a + b; }\n" - " function b() returns (uint r) { r = a({a: 1, a: 2}); }\n" - "}\n"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + char const* sourceCode = R"( + contract test { + function a(uint a, uint b) returns (uint r) { + r = a + b; + } + function b() returns (uint r) { + r = a({a: 1, a: 2}); + } + } + )"; + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(invalid_parameter_names_in_named_args) { - char const* sourceCode = "contract test {\n" - " function a(uint a, uint b) returns (uint r) { r = a + b; }\n" - " function b() returns (uint r) { r = a({a: 1, c: 2}); }\n" - "}\n"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + char const* sourceCode = R"( + contract test { + function a(uint a, uint b) returns (uint r) { + r = a + b; + } + function b() returns (uint r) { + r = a({a: 1, c: 2}); + } + } + )"; + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(empty_name_input_parameter) { char const* text = R"( contract test { - function f(uint){ + function f(uint) { } } - })"; - BOOST_CHECK(success(text)); + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(empty_name_return_parameter) { char const* text = R"( contract test { - function f() returns(bool){ + function f() returns(bool) { } } - })"; - BOOST_CHECK(success(text)); + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(empty_name_input_parameter_with_named_one) { char const* text = R"( contract test { - function f(uint, uint k) returns(uint ret_k){ + function f(uint, uint k) returns(uint ret_k) { return k; + } } - })"; - BOOST_CHECK(success(text)); + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(empty_name_return_parameter_with_named_one) { char const* text = R"( contract test { - function f() returns(uint ret_k, uint){ + function f() returns(uint ret_k, uint) { return 5; + } } - })"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(disallow_declaration_of_void_type) { - char const* sourceCode = "contract c { function f() { var (x) = f(); } }"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + char const* sourceCode = R"( + contract c { + function f() { var (x) = f(); } + } + )"; + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(overflow_caused_by_ether_units) { char const* sourceCodeFine = R"( contract c { - function c () - { - a = 115792089237316195423570985008687907853269984665640564039458; + function c () { + a = 115792089237316195423570985008687907853269984665640564039458; } uint256 a; - })"; + } + )"; ETH_TEST_CHECK_NO_THROW(parseAndAnalyse(sourceCodeFine), "Parsing and Resolving names failed"); char const* sourceCode = R"( contract c { - function c () - { + function c () { a = 115792089237316195423570985008687907853269984665640564039458 ether; } uint256 a; - })"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + } + )"; + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(exp_operator_exponent_too_big) @@ -1420,119 +1590,127 @@ BOOST_AUTO_TEST_CASE(exp_operator_exponent_too_big) char const* sourceCode = R"( contract test { function f() returns(uint d) { return 2 ** 10000000000; } - })"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + } + )"; + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(enum_member_access) { char const* text = R"( - contract test { - enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } - function test() - { - choices = ActionChoices.GoStraight; - } - ActionChoices choices; + contract test { + enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } + function test() + { + choices = ActionChoices.GoStraight; } + ActionChoices choices; + } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(enum_member_access_accross_contracts) { char const* text = R"( - contract Interface { - enum MyEnum { One, Two } - } - contract Impl { - function test() returns (Interface.MyEnum) { - return Interface.MyEnum.One; - } + contract Interface { + enum MyEnum { One, Two } + } + contract Impl { + function test() returns (Interface.MyEnum) { + return Interface.MyEnum.One; } + } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(enum_invalid_member_access) { char const* text = R"( - contract test { - enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } - function test() - { - choices = ActionChoices.RunAroundWavingYourHands; - } - ActionChoices choices; + contract test { + enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } + function test() { + choices = ActionChoices.RunAroundWavingYourHands; } + ActionChoices choices; + } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(enum_invalid_direct_member_access) { char const* text = R"( - contract test { - enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } - function test() - { - choices = Sit; - } - ActionChoices choices; + contract test { + enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } + function test() { + choices = Sit; } + ActionChoices choices; + } )"; - BOOST_CHECK(expectError(text) == Error::Type::DeclarationError); + CHECK_ERROR(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(enum_explicit_conversion_is_okay) { char const* text = R"( - contract test { - enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } - function test() - { - a = uint256(ActionChoices.GoStraight); - b = uint64(ActionChoices.Sit); - } - uint256 a; - uint64 b; + contract test { + enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } + function test() { + a = uint256(ActionChoices.GoStraight); + b = uint64(ActionChoices.Sit); } + uint256 a; + uint64 b; + } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(int_to_enum_explicit_conversion_is_okay) { char const* text = R"( - contract test { - enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } - function test() - { - a = 2; - b = ActionChoices(a); - } - uint256 a; - ActionChoices b; + contract test { + enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } + function test() { + a = 2; + b = ActionChoices(a); } + uint256 a; + ActionChoices b; + } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } -BOOST_AUTO_TEST_CASE(enum_implicit_conversion_is_not_okay) +BOOST_AUTO_TEST_CASE(enum_implicit_conversion_is_not_okay_256) { char const* text = R"( - contract test { - enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } - function test() - { - a = ActionChoices.GoStraight; - b = ActionChoices.Sit; - } - uint256 a; - uint64 b; + contract test { + enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } + function test() { + a = ActionChoices.GoStraight; } + uint256 a; + } + )"; + CHECK_ERROR(text, TypeError, ""); +} + +BOOST_AUTO_TEST_CASE(enum_implicit_conversion_is_not_okay_64) +{ + char const* text = R"( + contract test { + enum ActionChoices { GoLeft, GoRight, GoStraight, Sit } + function test() { + b = ActionChoices.Sit; + } + uint64 b; + } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(enum_to_enum_conversion_is_not_okay) @@ -1541,13 +1719,12 @@ BOOST_AUTO_TEST_CASE(enum_to_enum_conversion_is_not_okay) contract test { enum Paper { Up, Down, Left, Right } enum Ground { North, South, West, East } - function test() - { + function test() { Ground(Paper.Up); } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(enum_duplicate_values) @@ -1557,7 +1734,7 @@ BOOST_AUTO_TEST_CASE(enum_duplicate_values) enum ActionChoices { GoLeft, GoRight, GoLeft, Sit } } )"; - BOOST_CHECK(expectError(text) == Error::Type::DeclarationError); + CHECK_ERROR(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(enum_name_resolution_under_current_contract_name) @@ -1574,7 +1751,7 @@ BOOST_AUTO_TEST_CASE(enum_name_resolution_under_current_contract_name) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(private_visibility) @@ -1586,8 +1763,8 @@ BOOST_AUTO_TEST_CASE(private_visibility) contract derived is base { function g() { f(); } } - )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::DeclarationError); + )"; + CHECK_ERROR(sourceCode, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(private_visibility_via_explicit_base_access) @@ -1599,8 +1776,8 @@ BOOST_AUTO_TEST_CASE(private_visibility_via_explicit_base_access) contract derived is base { function g() { base.f(); } } - )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + )"; + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(external_visibility) @@ -1610,8 +1787,8 @@ BOOST_AUTO_TEST_CASE(external_visibility) function f() external {} function g() { f(); } } - )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::DeclarationError); + )"; + CHECK_ERROR(sourceCode, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(external_base_visibility) @@ -1623,8 +1800,8 @@ BOOST_AUTO_TEST_CASE(external_base_visibility) contract derived is base { function g() { base.f(); } } - )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + )"; + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(external_argument_assign) @@ -1633,8 +1810,8 @@ BOOST_AUTO_TEST_CASE(external_argument_assign) contract c { function f(uint a) external { a = 1; } } - )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + )"; + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(external_argument_increment) @@ -1643,8 +1820,8 @@ BOOST_AUTO_TEST_CASE(external_argument_increment) contract c { function f(uint a) external { a++; } } - )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + )"; + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(external_argument_delete) @@ -1653,8 +1830,8 @@ BOOST_AUTO_TEST_CASE(external_argument_delete) contract c { function f(uint a) external { delete a; } } - )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + )"; + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(test_for_bug_override_function_with_bytearray_type) @@ -1666,7 +1843,7 @@ BOOST_AUTO_TEST_CASE(test_for_bug_override_function_with_bytearray_type) contract Bike is Vehicle { function f(bytes _a) external returns (uint256 r) {r = 42;} } - )"; + )"; ETH_TEST_CHECK_NO_THROW(parseAndAnalyse(sourceCode), "Parsing and Name Resolving failed"); } @@ -1675,8 +1852,9 @@ BOOST_AUTO_TEST_CASE(array_with_nonconstant_length) char const* text = R"( contract c { function f(uint a) { uint8[a] x; } - })"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(array_copy_with_different_types1) @@ -1686,8 +1864,9 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types1) bytes a; uint[] b; function f() { b = a; } - })"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(array_copy_with_different_types2) @@ -1697,8 +1876,9 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types2) uint32[] a; uint8[] b; function f() { b = a; } - })"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(array_copy_with_different_types_conversion_possible) @@ -1708,8 +1888,9 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types_conversion_possible) uint32[] a; uint8[] b; function f() { a = b; } - })"; - BOOST_CHECK(success(text)); + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(array_copy_with_different_types_static_dynamic) @@ -1719,8 +1900,9 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types_static_dynamic) uint32[] a; uint8[80] b; function f() { a = b; } - })"; - BOOST_CHECK(success(text)); + } + )"; + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(array_copy_with_different_types_dynamic_static) @@ -1730,8 +1912,9 @@ BOOST_AUTO_TEST_CASE(array_copy_with_different_types_dynamic_static) uint[] a; uint[80] b; function f() { b = a; } - })"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(storage_variable_initialization_with_incorrect_type_int) @@ -1739,8 +1922,9 @@ BOOST_AUTO_TEST_CASE(storage_variable_initialization_with_incorrect_type_int) char const* text = R"( contract c { uint8 a = 1000; - })"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(storage_variable_initialization_with_incorrect_type_string) @@ -1748,8 +1932,9 @@ BOOST_AUTO_TEST_CASE(storage_variable_initialization_with_incorrect_type_string) char const* text = R"( contract c { uint a = "abc"; - })"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(test_fromElementaryTypeName) @@ -1864,7 +2049,8 @@ BOOST_AUTO_TEST_CASE(test_byte_is_alias_of_byte1) contract c { bytes arr; function f() { byte a = arr[0];} - })"; + } + )"; ETH_TEST_REQUIRE_NO_THROW(parseAndAnalyse(text), "Type resolving failed"); } @@ -1874,8 +2060,9 @@ BOOST_AUTO_TEST_CASE(assigning_value_to_const_variable) contract Foo { function changeIt() { x = 9; } uint constant x = 56; - })"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(complex_const_variable) @@ -1883,9 +2070,11 @@ BOOST_AUTO_TEST_CASE(complex_const_variable) //for now constant specifier is valid only for uint bytesXX and enums char const* text = R"( contract Foo { - mapping(uint => bool) constant mapVar; - })"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + mapping(uint => bool) x; + mapping(uint => bool) constant mapVar = x; + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(uninitialized_const_variable) @@ -1893,8 +2082,9 @@ BOOST_AUTO_TEST_CASE(uninitialized_const_variable) char const* text = R"( contract Foo { uint constant y; - })"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(overloaded_function_cannot_resolve) @@ -1906,7 +2096,7 @@ BOOST_AUTO_TEST_CASE(overloaded_function_cannot_resolve) function g() returns(uint) { return f(3, 5); } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(ambiguous_overloaded_function) @@ -1919,7 +2109,7 @@ BOOST_AUTO_TEST_CASE(ambiguous_overloaded_function) function g() returns(uint) { return f(1); } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(assignment_of_nonoverloaded_function) @@ -1942,7 +2132,7 @@ BOOST_AUTO_TEST_CASE(assignment_of_overloaded_function) function g() returns(uint) { var x = f; return x(7); } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(external_types_clash) @@ -1956,7 +2146,7 @@ BOOST_AUTO_TEST_CASE(external_types_clash) function f(uint8 a) { } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(override_changes_return_types) @@ -1969,7 +2159,7 @@ BOOST_AUTO_TEST_CASE(override_changes_return_types) function f(uint a) returns (uint8) { } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(multiple_constructors) @@ -1980,18 +2170,18 @@ BOOST_AUTO_TEST_CASE(multiple_constructors) function test() {} } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::DeclarationError); + CHECK_ERROR(sourceCode, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(equal_overload) { char const* sourceCode = R"( - contract test { + contract C { function test(uint a) returns (uint b) { } function test(uint a) external {} } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::DeclarationError); + CHECK_ERROR_ALLOW_MULTI(sourceCode, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(uninitialized_var) @@ -2001,7 +2191,7 @@ BOOST_AUTO_TEST_CASE(uninitialized_var) function f() returns (uint) { var x; return 2; } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(string) @@ -2015,6 +2205,26 @@ BOOST_AUTO_TEST_CASE(string) BOOST_CHECK_NO_THROW(parseAndAnalyse(sourceCode)); } +BOOST_AUTO_TEST_CASE(invalid_utf8_implicit) +{ + char const* sourceCode = R"( + contract C { + string s = "\xa0\x00"; + } + )"; + CHECK_ERROR(sourceCode, TypeError, "invalid UTF-8"); +} + +BOOST_AUTO_TEST_CASE(invalid_utf8_explicit) +{ + char const* sourceCode = R"( + contract C { + string s = string("\xa0\x00"); + } + )"; + CHECK_ERROR(sourceCode, TypeError, "Explicit type conversion not allowed"); +} + BOOST_AUTO_TEST_CASE(string_index) { char const* sourceCode = R"( @@ -2023,7 +2233,7 @@ BOOST_AUTO_TEST_CASE(string_index) function f() { var a = s[2]; } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(string_length) @@ -2034,7 +2244,7 @@ BOOST_AUTO_TEST_CASE(string_length) function f() { var a = s.length; } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(negative_integers_to_signed_out_of_bound) @@ -2044,7 +2254,7 @@ BOOST_AUTO_TEST_CASE(negative_integers_to_signed_out_of_bound) int8 public i = -129; } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(negative_integers_to_signed_min) @@ -2064,7 +2274,7 @@ BOOST_AUTO_TEST_CASE(positive_integers_to_signed_out_of_bound) int8 public j = 128; } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(positive_integers_to_signed_out_of_bound_max) @@ -2084,7 +2294,7 @@ BOOST_AUTO_TEST_CASE(negative_integers_to_unsigned) uint8 public x = -1; } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(positive_integers_to_unsigned_out_of_bound) @@ -2094,7 +2304,7 @@ BOOST_AUTO_TEST_CASE(positive_integers_to_unsigned_out_of_bound) uint8 public x = 700; } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(integer_boolean_operators) @@ -2102,15 +2312,15 @@ BOOST_AUTO_TEST_CASE(integer_boolean_operators) char const* sourceCode1 = R"( contract test { function() { uint x = 1; uint y = 2; x || y; } } )"; - BOOST_CHECK(expectError(sourceCode1) == Error::Type::TypeError); + CHECK_ERROR(sourceCode1, TypeError, ""); char const* sourceCode2 = R"( contract test { function() { uint x = 1; uint y = 2; x && y; } } )"; - BOOST_CHECK(expectError(sourceCode2) == Error::Type::TypeError); + CHECK_ERROR(sourceCode2, TypeError, ""); char const* sourceCode3 = R"( contract test { function() { uint x = 1; !x; } } )"; - BOOST_CHECK(expectError(sourceCode3) == Error::Type::TypeError); + CHECK_ERROR(sourceCode3, TypeError, ""); } BOOST_AUTO_TEST_CASE(exp_signed_variable) @@ -2118,15 +2328,15 @@ BOOST_AUTO_TEST_CASE(exp_signed_variable) char const* sourceCode1 = R"( contract test { function() { uint x = 3; int y = -4; x ** y; } } )"; - BOOST_CHECK(expectError(sourceCode1) == Error::Type::TypeError); + CHECK_ERROR(sourceCode1, TypeError, ""); char const* sourceCode2 = R"( contract test { function() { uint x = 3; int y = -4; y ** x; } } )"; - BOOST_CHECK(expectError(sourceCode2) == Error::Type::TypeError); + CHECK_ERROR(sourceCode2, TypeError, ""); char const* sourceCode3 = R"( contract test { function() { int x = -3; int y = -4; x ** y; } } )"; - BOOST_CHECK(expectError(sourceCode3) == Error::Type::TypeError); + CHECK_ERROR(sourceCode3, TypeError, ""); } BOOST_AUTO_TEST_CASE(reference_compare_operators) @@ -2134,11 +2344,11 @@ BOOST_AUTO_TEST_CASE(reference_compare_operators) char const* sourceCode1 = R"( contract test { bytes a; bytes b; function() { a == b; } } )"; - BOOST_CHECK(expectError(sourceCode1) == Error::Type::TypeError); + CHECK_ERROR(sourceCode1, TypeError, ""); char const* sourceCode2 = R"( contract test { struct s {uint a;} s x; s y; function() { x == y; } } )"; - BOOST_CHECK(expectError(sourceCode2) == Error::Type::TypeError); + CHECK_ERROR(sourceCode2, TypeError, ""); } BOOST_AUTO_TEST_CASE(overwrite_memory_location_external) @@ -2148,7 +2358,7 @@ BOOST_AUTO_TEST_CASE(overwrite_memory_location_external) function f(uint[] memory a) external {} } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(overwrite_storage_location_external) @@ -2158,7 +2368,7 @@ BOOST_AUTO_TEST_CASE(overwrite_storage_location_external) function f(uint[] storage a) external {} } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(storage_location_local_variables) @@ -2184,7 +2394,7 @@ BOOST_AUTO_TEST_CASE(no_mappings_in_memory_array) } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(assignment_mem_to_local_storage_variable) @@ -2198,7 +2408,7 @@ BOOST_AUTO_TEST_CASE(assignment_mem_to_local_storage_variable) } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(storage_assign_to_different_local_variable) @@ -2215,7 +2425,7 @@ BOOST_AUTO_TEST_CASE(storage_assign_to_different_local_variable) } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(no_delete_on_storage_pointers) @@ -2229,7 +2439,7 @@ BOOST_AUTO_TEST_CASE(no_delete_on_storage_pointers) } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(assignment_mem_storage_variable_directly) @@ -2256,7 +2466,7 @@ BOOST_AUTO_TEST_CASE(function_argument_mem_to_storage) } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(function_argument_storage_to_mem) @@ -2285,7 +2495,7 @@ BOOST_AUTO_TEST_CASE(mem_array_assignment_changes_base_type) } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(dynamic_return_types_not_possible) @@ -2300,7 +2510,7 @@ BOOST_AUTO_TEST_CASE(dynamic_return_types_not_possible) } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(memory_arrays_not_resizeable) @@ -2313,7 +2523,7 @@ BOOST_AUTO_TEST_CASE(memory_arrays_not_resizeable) } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(struct_constructor) @@ -2367,7 +2577,7 @@ BOOST_AUTO_TEST_CASE(literal_strings) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(invalid_integer_literal_exp) @@ -2379,7 +2589,7 @@ BOOST_AUTO_TEST_CASE(invalid_integer_literal_exp) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(memory_structs_with_mappings) @@ -2394,7 +2604,7 @@ BOOST_AUTO_TEST_CASE(memory_structs_with_mappings) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(string_bytes_conversion) @@ -2411,7 +2621,7 @@ BOOST_AUTO_TEST_CASE(string_bytes_conversion) function m() internal { string(b); } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(inheriting_from_library) @@ -2420,7 +2630,7 @@ BOOST_AUTO_TEST_CASE(inheriting_from_library) library Lib {} contract Test is Lib {} )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(inheriting_library) @@ -2429,7 +2639,7 @@ BOOST_AUTO_TEST_CASE(inheriting_library) contract Test {} library Lib is Test {} )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(library_having_variables) @@ -2437,7 +2647,7 @@ BOOST_AUTO_TEST_CASE(library_having_variables) char const* text = R"( library Lib { uint x; } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(valid_library) @@ -2445,7 +2655,7 @@ BOOST_AUTO_TEST_CASE(valid_library) char const* text = R"( library Lib { uint constant x = 9; } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(call_to_library_function) @@ -2460,7 +2670,7 @@ BOOST_AUTO_TEST_CASE(call_to_library_function) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(creating_contract_within_the_contract) @@ -2470,7 +2680,7 @@ BOOST_AUTO_TEST_CASE(creating_contract_within_the_contract) function f() { var x = new Test(); } } )"; - BOOST_CHECK(expectError(sourceCode) == Error::Type::TypeError); + CHECK_ERROR(sourceCode, TypeError, ""); } BOOST_AUTO_TEST_CASE(array_out_of_bound_access) @@ -2484,7 +2694,7 @@ BOOST_AUTO_TEST_CASE(array_out_of_bound_access) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(literal_string_to_storage_pointer) @@ -2494,7 +2704,7 @@ BOOST_AUTO_TEST_CASE(literal_string_to_storage_pointer) function f() { string x = "abc"; } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(non_initialized_references) @@ -2513,7 +2723,7 @@ BOOST_AUTO_TEST_CASE(non_initialized_references) } )"; - BOOST_CHECK(expectError(text, true) == Error::Type::Warning); + CHECK_WARNING(text, "Uninitialized storage pointer"); } BOOST_AUTO_TEST_CASE(sha3_with_large_integer_constant) @@ -2524,7 +2734,7 @@ BOOST_AUTO_TEST_CASE(sha3_with_large_integer_constant) function f() { sha3(2**500); } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(cyclic_binary_dependency) @@ -2534,7 +2744,7 @@ BOOST_AUTO_TEST_CASE(cyclic_binary_dependency) contract B { function f() { new C(); } } contract C { function f() { new A(); } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(cyclic_binary_dependency_via_inheritance) @@ -2544,7 +2754,7 @@ BOOST_AUTO_TEST_CASE(cyclic_binary_dependency_via_inheritance) contract B { function f() { new C(); } } contract C { function f() { new A(); } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_fail) @@ -2552,7 +2762,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_fail) char const* text = R"( contract C { function f() { var (x,y); } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fine) @@ -2572,7 +2782,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fine) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_1) @@ -2583,7 +2793,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_1) function f() { var (a, b, ) = one(); } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_2) { @@ -2593,7 +2803,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_2) function f() { var (a, , ) = one(); } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_3) @@ -2604,7 +2814,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_3) function f() { var (, , a) = one(); } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_4) @@ -2615,7 +2825,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_4) function f() { var (, a, b) = one(); } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(tuples) @@ -2630,7 +2840,7 @@ BOOST_AUTO_TEST_CASE(tuples) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(tuples_empty_components) @@ -2642,7 +2852,7 @@ BOOST_AUTO_TEST_CASE(tuples_empty_components) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_5) @@ -2653,7 +2863,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_5) function f() { var (,) = one(); } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_6) @@ -2664,7 +2874,7 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration_wildcards_fail_6) function f() { var (a, b, c) = two(); } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(member_access_parser_ambiguity) @@ -2685,7 +2895,7 @@ BOOST_AUTO_TEST_CASE(member_access_parser_ambiguity) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(using_for_library) @@ -2696,7 +2906,7 @@ BOOST_AUTO_TEST_CASE(using_for_library) using D for uint; } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(using_for_not_library) @@ -2707,7 +2917,7 @@ BOOST_AUTO_TEST_CASE(using_for_not_library) using D for uint; } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(using_for_function_exists) @@ -2721,7 +2931,7 @@ BOOST_AUTO_TEST_CASE(using_for_function_exists) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(using_for_function_on_int) @@ -2735,7 +2945,7 @@ BOOST_AUTO_TEST_CASE(using_for_function_on_int) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(using_for_function_on_struct) @@ -2750,7 +2960,7 @@ BOOST_AUTO_TEST_CASE(using_for_function_on_struct) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(using_for_overload) @@ -2769,7 +2979,7 @@ BOOST_AUTO_TEST_CASE(using_for_overload) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(using_for_by_name) @@ -2784,7 +2994,7 @@ BOOST_AUTO_TEST_CASE(using_for_by_name) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(using_for_mismatch) @@ -2798,7 +3008,7 @@ BOOST_AUTO_TEST_CASE(using_for_mismatch) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(using_for_not_used) @@ -2814,7 +3024,18 @@ BOOST_AUTO_TEST_CASE(using_for_not_used) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); +} + +BOOST_AUTO_TEST_CASE(library_memory_struct) +{ + char const* text = R"( + library c { + struct S { uint x; } + function f() returns (S ) {} + } + )"; + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(using_for_arbitrary_mismatch) @@ -2829,7 +3050,7 @@ BOOST_AUTO_TEST_CASE(using_for_arbitrary_mismatch) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(bound_function_in_var) @@ -2845,7 +3066,7 @@ BOOST_AUTO_TEST_CASE(bound_function_in_var) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(create_memory_arrays) @@ -2863,7 +3084,7 @@ BOOST_AUTO_TEST_CASE(create_memory_arrays) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(mapping_in_memory_array) @@ -2875,7 +3096,7 @@ BOOST_AUTO_TEST_CASE(mapping_in_memory_array) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(new_for_non_array) @@ -2887,7 +3108,7 @@ BOOST_AUTO_TEST_CASE(new_for_non_array) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(invalid_args_creating_memory_array) @@ -2899,7 +3120,7 @@ BOOST_AUTO_TEST_CASE(invalid_args_creating_memory_array) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(function_overload_array_type) @@ -2910,7 +3131,7 @@ BOOST_AUTO_TEST_CASE(function_overload_array_type) function f(int[] values); } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(inline_array_declaration_and_passing_implicit_conversion) @@ -2926,7 +3147,7 @@ BOOST_AUTO_TEST_CASE(inline_array_declaration_and_passing_implicit_conversion) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(inline_array_declaration_and_passing_implicit_conversion_strings) @@ -2941,7 +3162,7 @@ BOOST_AUTO_TEST_CASE(inline_array_declaration_and_passing_implicit_conversion_st } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(inline_array_declaration_const_int_conversion) @@ -2954,7 +3175,7 @@ BOOST_AUTO_TEST_CASE(inline_array_declaration_const_int_conversion) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(inline_array_declaration_const_string_conversion) @@ -2967,7 +3188,7 @@ BOOST_AUTO_TEST_CASE(inline_array_declaration_const_string_conversion) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(inline_array_declaration_no_type) @@ -2979,7 +3200,7 @@ BOOST_AUTO_TEST_CASE(inline_array_declaration_no_type) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(inline_array_declaration_no_type_strings) @@ -2991,7 +3212,7 @@ BOOST_AUTO_TEST_CASE(inline_array_declaration_no_type_strings) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(inline_struct_declaration_arrays) @@ -3007,7 +3228,7 @@ BOOST_AUTO_TEST_CASE(inline_struct_declaration_arrays) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(invalid_types_in_inline_array) @@ -3019,7 +3240,7 @@ BOOST_AUTO_TEST_CASE(invalid_types_in_inline_array) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(dynamic_inline_array) @@ -3031,7 +3252,7 @@ BOOST_AUTO_TEST_CASE(dynamic_inline_array) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(lvalues_as_inline_array) @@ -3044,7 +3265,7 @@ BOOST_AUTO_TEST_CASE(lvalues_as_inline_array) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(break_not_in_loop) @@ -3057,7 +3278,7 @@ BOOST_AUTO_TEST_CASE(break_not_in_loop) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::SyntaxError); + CHECK_ERROR(text, SyntaxError, ""); } BOOST_AUTO_TEST_CASE(continue_not_in_loop) @@ -3070,7 +3291,7 @@ BOOST_AUTO_TEST_CASE(continue_not_in_loop) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::SyntaxError); + CHECK_ERROR(text, SyntaxError, ""); } BOOST_AUTO_TEST_CASE(continue_not_in_loop_2) @@ -3085,7 +3306,7 @@ BOOST_AUTO_TEST_CASE(continue_not_in_loop_2) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::SyntaxError); + CHECK_ERROR(text, SyntaxError, ""); } BOOST_AUTO_TEST_CASE(invalid_different_types_for_conditional_expression) @@ -3097,7 +3318,7 @@ BOOST_AUTO_TEST_CASE(invalid_different_types_for_conditional_expression) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(left_value_in_conditional_expression_not_supported_yet) @@ -3111,7 +3332,7 @@ BOOST_AUTO_TEST_CASE(left_value_in_conditional_expression_not_supported_yet) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR_ALLOW_MULTI(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(conditional_expression_with_different_struct) @@ -3125,13 +3346,13 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_different_struct) uint x; } function f() { - s1 x; - s2 y; + s1 memory x; + s2 memory y; true ? x : y; } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(conditional_expression_with_different_function_type) @@ -3146,7 +3367,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_different_function_type) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(conditional_expression_with_different_enum) @@ -3164,7 +3385,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_different_enum) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(conditional_expression_with_different_mapping) @@ -3179,7 +3400,7 @@ BOOST_AUTO_TEST_CASE(conditional_expression_with_different_mapping) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(conditional_with_all_types) @@ -3261,7 +3482,7 @@ BOOST_AUTO_TEST_CASE(conditional_with_all_types) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(constructor_call_invalid_arg_count) @@ -3276,7 +3497,7 @@ BOOST_AUTO_TEST_CASE(constructor_call_invalid_arg_count) } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(index_access_for_bytes) @@ -3289,7 +3510,7 @@ BOOST_AUTO_TEST_CASE(index_access_for_bytes) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(uint7_and_uintM_as_identifier) @@ -3305,7 +3526,7 @@ BOOST_AUTO_TEST_CASE(uint7_and_uintM_as_identifier) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(varM_disqualified_as_keyword) @@ -3343,7 +3564,7 @@ BOOST_AUTO_TEST_CASE(bytes10abc_is_identifier) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(int10abc_is_identifier) @@ -3356,7 +3577,7 @@ BOOST_AUTO_TEST_CASE(int10abc_is_identifier) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(library_functions_do_not_have_value) @@ -3440,7 +3661,7 @@ BOOST_AUTO_TEST_CASE(fixed_type_int_conversion) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(fixed_type_rational_int_conversion) @@ -3453,7 +3674,7 @@ BOOST_AUTO_TEST_CASE(fixed_type_rational_int_conversion) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(fixed_type_rational_fraction_conversion) @@ -3466,7 +3687,7 @@ BOOST_AUTO_TEST_CASE(fixed_type_rational_fraction_conversion) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(invalid_int_implicit_conversion_from_fixed) @@ -3492,7 +3713,7 @@ BOOST_AUTO_TEST_CASE(rational_unary_operation) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(leading_zero_rationals_convert) @@ -3507,7 +3728,7 @@ BOOST_AUTO_TEST_CASE(leading_zero_rationals_convert) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(size_capabilities_of_fixed_point_types) @@ -3524,7 +3745,7 @@ BOOST_AUTO_TEST_CASE(size_capabilities_of_fixed_point_types) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(fixed_type_invalid_implicit_conversion_size) @@ -3563,7 +3784,7 @@ BOOST_AUTO_TEST_CASE(fixed_type_valid_explicit_conversions) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(invalid_array_declaration_with_rational) @@ -3607,7 +3828,7 @@ BOOST_AUTO_TEST_CASE(fixed_to_bytes_implicit_conversion) char const* text = R"( contract test { function f() { - fixed a = 3.2; + fixed a = 3.25; bytes32 c = a; } } @@ -3625,7 +3846,7 @@ BOOST_AUTO_TEST_CASE(mapping_with_fixed_literal) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(fixed_points_inside_structs) @@ -3639,7 +3860,7 @@ BOOST_AUTO_TEST_CASE(fixed_points_inside_structs) myStruct a = myStruct(3.125, 3); } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(inline_array_fixed_types) @@ -3651,7 +3872,7 @@ BOOST_AUTO_TEST_CASE(inline_array_fixed_types) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(inline_array_rationals) @@ -3663,7 +3884,7 @@ BOOST_AUTO_TEST_CASE(inline_array_rationals) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(rational_index_access) @@ -3694,17 +3915,50 @@ BOOST_AUTO_TEST_CASE(rational_to_fixed_literal_expression) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } -BOOST_AUTO_TEST_CASE(rational_as_exponent_value) +BOOST_AUTO_TEST_CASE(rational_as_exponent_value_neg_decimal) { char const* text = R"( contract test { function f() { fixed g = 2 ** -2.2; + } + } + )"; + BOOST_CHECK(!success(text)); +} + +BOOST_AUTO_TEST_CASE(rational_as_exponent_value_pos_decimal) +{ + char const* text = R"( + contract test { + function f() { ufixed b = 3 ** 2.5; + } + } + )"; + BOOST_CHECK(!success(text)); +} + +BOOST_AUTO_TEST_CASE(rational_as_exponent_half) +{ + char const* text = R"( + contract test { + function f() { ufixed24x24 b = 2 ** (1/2); + } + } + )"; + BOOST_CHECK(!success(text)); +} + +BOOST_AUTO_TEST_CASE(rational_as_exponent_value_neg_quarter) +{ + char const* text = R"( + contract test { + function f() { fixed40x40 c = 42 ** (-1/4); } } @@ -3712,15 +3966,48 @@ BOOST_AUTO_TEST_CASE(rational_as_exponent_value) BOOST_CHECK(!success(text)); } -BOOST_AUTO_TEST_CASE(fixed_point_casting_exponents) +BOOST_AUTO_TEST_CASE(fixed_point_casting_exponents_15) { char const* text = R"( contract test { function f() { ufixed a = 3 ** ufixed(1.5); + } + } + )"; + BOOST_CHECK(!success(text)); +} + +BOOST_AUTO_TEST_CASE(fixed_point_casting_exponents_half) +{ + char const* text = R"( + contract test { + function f() { ufixed b = 2 ** ufixed(1/2); + } + } + )"; + BOOST_CHECK(!success(text)); +} + +BOOST_AUTO_TEST_CASE(fixed_point_casting_exponents_neg) +{ + char const* text = R"( + contract test { + function f() { fixed c = 42 ** fixed(-1/4); - fixed d = 16 ** fixed(-0.33); + } + } + )"; + BOOST_CHECK(!success(text)); +} + +BOOST_AUTO_TEST_CASE(fixed_point_casting_exponents_neg_decimal) +{ + char const* text = R"( + contract test { + function f() { + fixed d = 16 ** fixed(-0.5); } } )"; @@ -3738,7 +4025,7 @@ BOOST_AUTO_TEST_CASE(var_capable_of_holding_constant_rationals) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(var_and_rational_with_tuple) @@ -3750,7 +4037,7 @@ BOOST_AUTO_TEST_CASE(var_and_rational_with_tuple) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(var_handle_divided_integers) @@ -3762,7 +4049,7 @@ BOOST_AUTO_TEST_CASE(var_handle_divided_integers) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(rational_bitnot_unary_operation) @@ -3770,7 +4057,7 @@ BOOST_AUTO_TEST_CASE(rational_bitnot_unary_operation) char const* text = R"( contract test { function f() { - fixed a = ~3.56; + fixed a = ~3.5; } } )"; @@ -3782,7 +4069,7 @@ BOOST_AUTO_TEST_CASE(rational_bitor_binary_operation) char const* text = R"( contract test { function f() { - fixed a = 1.56 | 3; + fixed a = 1.5 | 3; } } )"; @@ -3794,7 +4081,7 @@ BOOST_AUTO_TEST_CASE(rational_bitxor_binary_operation) char const* text = R"( contract test { function f() { - fixed a = 1.56 ^ 3; + fixed a = 1.75 ^ 3; } } )"; @@ -3806,7 +4093,7 @@ BOOST_AUTO_TEST_CASE(rational_bitand_binary_operation) char const* text = R"( contract test { function f() { - fixed a = 1.56 & 3; + fixed a = 1.75 & 3; } } )"; @@ -3823,7 +4110,7 @@ BOOST_AUTO_TEST_CASE(zero_handling) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(missing_bool_conversion) @@ -3835,7 +4122,7 @@ BOOST_AUTO_TEST_CASE(missing_bool_conversion) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(integer_and_fixed_interaction) @@ -3847,7 +4134,7 @@ BOOST_AUTO_TEST_CASE(integer_and_fixed_interaction) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(signed_rational_modulus) @@ -3861,7 +4148,7 @@ BOOST_AUTO_TEST_CASE(signed_rational_modulus) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(one_divided_by_three_integer_conversion) @@ -3886,7 +4173,7 @@ BOOST_AUTO_TEST_CASE(unused_return_value) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(unused_return_value_send) @@ -3898,7 +4185,7 @@ BOOST_AUTO_TEST_CASE(unused_return_value_send) } } )"; - BOOST_CHECK(expectError(text, true) == Error::Type::Warning); + CHECK_WARNING(text, "Return value of low-level calls not used"); } BOOST_AUTO_TEST_CASE(unused_return_value_call) @@ -3910,7 +4197,7 @@ BOOST_AUTO_TEST_CASE(unused_return_value_call) } } )"; - BOOST_CHECK(expectError(text, true) == Error::Type::Warning); + CHECK_WARNING(text, "Return value of low-level calls not used"); } BOOST_AUTO_TEST_CASE(unused_return_value_call_value) @@ -3922,7 +4209,7 @@ BOOST_AUTO_TEST_CASE(unused_return_value_call_value) } } )"; - BOOST_CHECK(expectError(text, true) == Error::Type::Warning); + CHECK_WARNING(text, "Return value of low-level calls not used"); } BOOST_AUTO_TEST_CASE(unused_return_value_callcode) @@ -3934,7 +4221,7 @@ BOOST_AUTO_TEST_CASE(unused_return_value_callcode) } } )"; - BOOST_CHECK(expectError(text, true) == Error::Type::Warning); + CHECK_WARNING(text, "Return value of low-level calls not used"); } BOOST_AUTO_TEST_CASE(unused_return_value_delegatecall) @@ -3946,7 +4233,7 @@ BOOST_AUTO_TEST_CASE(unused_return_value_delegatecall) } } )"; - BOOST_CHECK(expectError(text, true) == Error::Type::Warning); + CHECK_WARNING(text, "Return value of low-level calls not used"); } BOOST_AUTO_TEST_CASE(modifier_without_underscore) @@ -3956,7 +4243,7 @@ BOOST_AUTO_TEST_CASE(modifier_without_underscore) modifier m() {} } )"; - BOOST_CHECK(expectError(text) == Error::Type::SyntaxError); + CHECK_ERROR(text, SyntaxError, ""); } BOOST_AUTO_TEST_CASE(payable_in_library) @@ -3966,7 +4253,7 @@ BOOST_AUTO_TEST_CASE(payable_in_library) function f() payable {} } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(payable_external) @@ -3976,7 +4263,7 @@ BOOST_AUTO_TEST_CASE(payable_external) function f() payable external {} } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(payable_internal) @@ -3986,7 +4273,7 @@ BOOST_AUTO_TEST_CASE(payable_internal) function f() payable internal {} } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(payable_private) @@ -3996,7 +4283,7 @@ BOOST_AUTO_TEST_CASE(payable_private) function f() payable private {} } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(illegal_override_payable) @@ -4005,7 +4292,7 @@ BOOST_AUTO_TEST_CASE(illegal_override_payable) contract B { function f() payable {} } contract C is B { function f() {} } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(illegal_override_payable_nonpayable) @@ -4014,7 +4301,7 @@ BOOST_AUTO_TEST_CASE(illegal_override_payable_nonpayable) contract B { function f() {} } contract C is B { function f() payable {} } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(payable_constant_conflict) @@ -4022,7 +4309,7 @@ BOOST_AUTO_TEST_CASE(payable_constant_conflict) char const* text = R"( contract C { function f() payable constant {} } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(calling_payable) @@ -4035,7 +4322,7 @@ BOOST_AUTO_TEST_CASE(calling_payable) function g() { r.pay.value(10)(); } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(calling_nonpayable) @@ -4046,7 +4333,7 @@ BOOST_AUTO_TEST_CASE(calling_nonpayable) function f() { (new receiver()).nopay.value(10)(); } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(non_payable_constructor) @@ -4062,7 +4349,7 @@ BOOST_AUTO_TEST_CASE(non_payable_constructor) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(warn_nonpresent_pragma) @@ -4071,7 +4358,7 @@ BOOST_AUTO_TEST_CASE(warn_nonpresent_pragma) auto sourceAndError = parseAnalyseAndReturnError(text, true, false); BOOST_REQUIRE(!!sourceAndError.second); BOOST_REQUIRE(!!sourceAndError.first); - BOOST_CHECK(*sourceAndError.second == Error::Type::Warning); + BOOST_CHECK(searchErrorMessage(*sourceAndError.second, "Source file does not specify required compiler version!")); } BOOST_AUTO_TEST_CASE(unsatisfied_version) @@ -4079,7 +4366,7 @@ BOOST_AUTO_TEST_CASE(unsatisfied_version) char const* text = R"( pragma solidity ^99.99.0; )"; - BOOST_CHECK(expectError(text, true) == Error::Type::SyntaxError); + BOOST_CHECK(expectError(text, true).type() == Error::Type::SyntaxError); } BOOST_AUTO_TEST_CASE(constant_constructor) @@ -4089,7 +4376,7 @@ BOOST_AUTO_TEST_CASE(constant_constructor) function test() constant {} } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(external_constructor) @@ -4099,7 +4386,7 @@ BOOST_AUTO_TEST_CASE(external_constructor) function test() external {} } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(invalid_array_as_statement) @@ -4107,10 +4394,10 @@ BOOST_AUTO_TEST_CASE(invalid_array_as_statement) char const* text = R"( contract test { struct S { uint x; } - function test(uint k) { S[k]; } + function test(uint k) { S[k]; } } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(using_directive_for_missing_selftype) @@ -4129,7 +4416,7 @@ BOOST_AUTO_TEST_CASE(using_directive_for_missing_selftype) } } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(function_type) @@ -4141,7 +4428,7 @@ BOOST_AUTO_TEST_CASE(function_type) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(function_type_parameter) @@ -4153,7 +4440,7 @@ BOOST_AUTO_TEST_CASE(function_type_parameter) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(function_type_returned) @@ -4165,7 +4452,7 @@ BOOST_AUTO_TEST_CASE(function_type_returned) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(private_function_type) @@ -4177,7 +4464,7 @@ BOOST_AUTO_TEST_CASE(private_function_type) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(public_function_type) @@ -4189,7 +4476,7 @@ BOOST_AUTO_TEST_CASE(public_function_type) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(payable_internal_function_type) @@ -4199,7 +4486,7 @@ BOOST_AUTO_TEST_CASE(payable_internal_function_type) function (uint) internal payable returns (uint) x; } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(call_value_on_non_payable_function_type) @@ -4212,7 +4499,7 @@ BOOST_AUTO_TEST_CASE(call_value_on_non_payable_function_type) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(external_function_type_returning_internal) @@ -4222,7 +4509,7 @@ BOOST_AUTO_TEST_CASE(external_function_type_returning_internal) function() external returns (function () internal) x; } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(external_function_type_taking_internal) @@ -4232,7 +4519,7 @@ BOOST_AUTO_TEST_CASE(external_function_type_taking_internal) function(function () internal) external x; } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(call_value_on_payable_function_type) @@ -4245,7 +4532,7 @@ BOOST_AUTO_TEST_CASE(call_value_on_payable_function_type) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter) @@ -4258,7 +4545,7 @@ BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(internal_function_returned_from_public_function) @@ -4270,7 +4557,7 @@ BOOST_AUTO_TEST_CASE(internal_function_returned_from_public_function) } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter_in_library_internal) @@ -4281,7 +4568,7 @@ BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter_in_library_internal } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter_in_library_external) @@ -4292,7 +4579,7 @@ BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter_in_library_external } } )"; - BOOST_CHECK(expectError(text) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(function_type_arrays) @@ -4309,7 +4596,7 @@ BOOST_AUTO_TEST_CASE(function_type_arrays) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(delete_function_type) @@ -4330,7 +4617,7 @@ BOOST_AUTO_TEST_CASE(delete_function_type) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(delete_function_type_invalid) @@ -4342,7 +4629,7 @@ BOOST_AUTO_TEST_CASE(delete_function_type_invalid) } } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(delete_external_function_type_invalid) @@ -4354,7 +4641,7 @@ BOOST_AUTO_TEST_CASE(delete_external_function_type_invalid) } } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(invalid_fixed_point_literal) @@ -4366,7 +4653,7 @@ BOOST_AUTO_TEST_CASE(invalid_fixed_point_literal) } } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(shift_constant_left_negative_rvalue) @@ -4376,7 +4663,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_left_negative_rvalue) uint public a = 0x42 << -8; } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(shift_constant_right_negative_rvalue) @@ -4386,7 +4673,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_right_negative_rvalue) uint public a = 0x42 >> -8; } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(shift_constant_left_excessive_rvalue) @@ -4396,7 +4683,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_left_excessive_rvalue) uint public a = 0x42 << 0x100000000; } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(shift_constant_right_excessive_rvalue) @@ -4406,7 +4693,7 @@ BOOST_AUTO_TEST_CASE(shift_constant_right_excessive_rvalue) uint public a = 0x42 >> 0x100000000; } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); } BOOST_AUTO_TEST_CASE(inline_assembly_unbalanced_positive_stack) @@ -4420,7 +4707,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_unbalanced_positive_stack) } } )"; - BOOST_CHECK(expectError(text, true) == Error::Type::Warning); + CHECK_WARNING(text, "Inline assembly block is not balanced"); } BOOST_AUTO_TEST_CASE(inline_assembly_unbalanced_negative_stack) @@ -4434,7 +4721,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_unbalanced_negative_stack) } } )"; - BOOST_CHECK(expectError(text, true) == Error::Type::Warning); + CHECK_WARNING(text, "Inline assembly block is not balanced"); } BOOST_AUTO_TEST_CASE(inline_assembly_in_modifier) @@ -4452,7 +4739,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_in_modifier) } } )"; - BOOST_CHECK(success(text)); + CHECK_SUCCESS(text); } BOOST_AUTO_TEST_CASE(inline_assembly_storage) @@ -4463,11 +4750,12 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage) function f() { assembly { x := 2 + pop } } } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::DeclarationError); + CHECK_ERROR(text, DeclarationError, "not found, not unique or not lvalue."); } BOOST_AUTO_TEST_CASE(inline_assembly_storage_in_modifiers) @@ -4478,6 +4766,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage_in_modifiers) modifier m { assembly { x := 2 + pop } _; } @@ -4485,7 +4774,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage_in_modifiers) } } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::DeclarationError); + CHECK_ERROR(text, DeclarationError, ""); } BOOST_AUTO_TEST_CASE(invalid_mobile_type) @@ -4498,7 +4787,93 @@ BOOST_AUTO_TEST_CASE(invalid_mobile_type) } } )"; - BOOST_CHECK(expectError(text, false) == Error::Type::TypeError); + CHECK_ERROR(text, TypeError, ""); +} + +BOOST_AUTO_TEST_CASE(warns_msg_value_in_non_payable_public_function) +{ + char const* text = R"( + contract C { + function f() { + msg.value; + } + } + )"; + CHECK_WARNING(text, "\"msg.value\" used in non-payable function. Do you want to add the \"payable\" modifier to this function?"); +} + +BOOST_AUTO_TEST_CASE(does_not_warn_msg_value_in_payable_function) +{ + char const* text = R"( + contract C { + function f() payable { + msg.value; + } + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + +BOOST_AUTO_TEST_CASE(does_not_warn_msg_value_in_internal_function) +{ + char const* text = R"( + contract C { + function f() internal { + msg.value; + } + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + +BOOST_AUTO_TEST_CASE(does_not_warn_msg_value_in_library) +{ + char const* text = R"( + library C { + function f() { + msg.value; + } + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + +BOOST_AUTO_TEST_CASE(does_not_warn_non_magic_msg_value) +{ + char const* text = R"( + contract C { + struct msg { + uint256 value; + } + + function f() { + msg.value; + } + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + +BOOST_AUTO_TEST_CASE(does_not_warn_msg_value_in_modifier_following_non_payable_public_function) +{ + char const* text = R"( + contract c { + function f() { } + modifier m() { msg.value; _; } + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); +} + +BOOST_AUTO_TEST_CASE(assignment_to_constant) +{ + char const* text = R"( + contract c { + uint constant a = 1; + function f() { a = 2; } + } + )"; + CHECK_ERROR(text, TypeError, "Cannot assign to a constant variable."); } BOOST_AUTO_TEST_SUITE_END() diff --git a/test/libsolidity/SolidityNatspecJSON.cpp b/test/libsolidity/SolidityNatspecJSON.cpp index 49844f15..e32264c4 100644 --- a/test/libsolidity/SolidityNatspecJSON.cpp +++ b/test/libsolidity/SolidityNatspecJSON.cpp @@ -1,18 +1,18 @@ /* - This file is part of cpp-ethereum. + This file is part of solidity. - cpp-ethereum is free software: you can redistribute it and/or modify + 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. - cpp-ethereum is distributed in the hope that it will be useful, + 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. + along with solidity. If not, see <http://www.gnu.org/licenses/>. */ /** * @author Lefteris Karapetsas <lefteris@ethdev.com> @@ -76,10 +76,12 @@ BOOST_FIXTURE_TEST_SUITE(SolidityNatspecJSON, DocumentationChecker) BOOST_AUTO_TEST_CASE(user_basic_test) { - char const* sourceCode = "contract test {\n" - " /// @notice Multiplies `a` by 7\n" - " function mul(uint a) returns(uint d) { return a * 7; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /// @notice Multiplies `a` by 7 + function mul(uint a) returns(uint d) { return a * 7; } + } + )"; char const* natspec = "{" "\"methods\":{" @@ -91,11 +93,13 @@ BOOST_AUTO_TEST_CASE(user_basic_test) BOOST_AUTO_TEST_CASE(dev_and_user_basic_test) { - char const* sourceCode = "contract test {\n" - " /// @notice Multiplies `a` by 7\n" - " /// @dev Multiplies a number by 7\n" - " function mul(uint a) returns(uint d) { return a * 7; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /// @notice Multiplies `a` by 7 + /// @dev Multiplies a number by 7 + function mul(uint a) returns(uint d) { return a * 7; } + } + )"; char const* devNatspec = "{" "\"methods\":{" @@ -116,14 +120,15 @@ BOOST_AUTO_TEST_CASE(dev_and_user_basic_test) BOOST_AUTO_TEST_CASE(user_multiline_comment) { - char const* sourceCode = "contract test {\n" - " /// @notice Multiplies `a` by 7\n" - " /// and then adds `b`\n" - " function mul_and_add(uint a, uint256 b) returns(uint256 d)\n" - " {\n" - " return (a * 7) + b;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /// @notice Multiplies `a` by 7 + /// and then adds `b` + function mul_and_add(uint a, uint256 b) returns(uint256 d) { + return (a * 7) + b; + } + } + )"; char const* natspec = "{" "\"methods\":{" @@ -135,24 +140,24 @@ BOOST_AUTO_TEST_CASE(user_multiline_comment) BOOST_AUTO_TEST_CASE(user_multiple_functions) { - char const* sourceCode = "contract test {\n" - " /// @notice Multiplies `a` by 7 and then adds `b`\n" - " function mul_and_add(uint a, uint256 b) returns(uint256 d)\n" - " {\n" - " return (a * 7) + b;\n" - " }\n" - "\n" - " /// @notice Divides `input` by `div`\n" - " function divide(uint input, uint div) returns(uint d)\n" - " {\n" - " return input / div;\n" - " }\n" - " /// @notice Subtracts 3 from `input`\n" - " function sub(int input) returns(int d)\n" - " {\n" - " return input - 3;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /// @notice Multiplies `a` by 7 and then adds `b` + function mul_and_add(uint a, uint256 b) returns(uint256 d) { + return (a * 7) + b; + } + + /// @notice Divides `input` by `div` + function divide(uint input, uint div) returns(uint d) { + return input / div; + } + + /// @notice Subtracts 3 from `input` + function sub(int input) returns(int d) { + return input - 3; + } + } + )"; char const* natspec = "{" "\"methods\":{" @@ -166,8 +171,9 @@ BOOST_AUTO_TEST_CASE(user_multiple_functions) BOOST_AUTO_TEST_CASE(user_empty_contract) { - char const* sourceCode = "contract test {\n" - "}\n"; + char const* sourceCode = R"( + contract test { } + )"; char const* natspec = "{\"methods\":{} }"; @@ -176,13 +182,16 @@ BOOST_AUTO_TEST_CASE(user_empty_contract) BOOST_AUTO_TEST_CASE(dev_and_user_no_doc) { - char const* sourceCode = "contract test {\n" - " function mul(uint a) returns(uint d) { return a * 7; }\n" - " function sub(int input) returns(int d)\n" - " {\n" - " return input - 3;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + function mul(uint a) returns(uint d) { + return a * 7; + } + function sub(int input) returns(int d) { + return input - 3; + } + } + )"; char const* devNatspec = "{\"methods\":{}}"; char const* userNatspec = "{\"methods\":{}}"; @@ -193,13 +202,15 @@ BOOST_AUTO_TEST_CASE(dev_and_user_no_doc) BOOST_AUTO_TEST_CASE(dev_desc_after_nl) { - char const* sourceCode = "contract test {\n" - " /// @dev\n" - " /// Multiplies a number by 7 and adds second parameter\n" - " /// @param a Documentation for the first parameter\n" - " /// @param second Documentation for the second parameter\n" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /// @dev + /// Multiplies a number by 7 and adds second parameter + /// @param a Documentation for the first parameter + /// @param second Documentation for the second parameter + function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + } + )"; char const* natspec = "{" "\"methods\":{" @@ -217,12 +228,14 @@ BOOST_AUTO_TEST_CASE(dev_desc_after_nl) BOOST_AUTO_TEST_CASE(dev_multiple_params) { - char const* sourceCode = "contract test {\n" - " /// @dev Multiplies a number by 7 and adds second parameter\n" - " /// @param a Documentation for the first parameter\n" - " /// @param second Documentation for the second parameter\n" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /// @dev Multiplies a number by 7 and adds second parameter + /// @param a Documentation for the first parameter + /// @param second Documentation for the second parameter + function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + } + )"; char const* natspec = "{" "\"methods\":{" @@ -240,13 +253,15 @@ BOOST_AUTO_TEST_CASE(dev_multiple_params) BOOST_AUTO_TEST_CASE(dev_mutiline_param_description) { - char const* sourceCode = "contract test {\n" - " /// @dev Multiplies a number by 7 and adds second parameter\n" - " /// @param a Documentation for the first parameter starts here.\n" - " /// Since it's a really complicated parameter we need 2 lines\n" - " /// @param second Documentation for the second parameter\n" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /// @dev Multiplies a number by 7 and adds second parameter + /// @param a Documentation for the first parameter starts here. + /// Since it's a really complicated parameter we need 2 lines + /// @param second Documentation for the second parameter + function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + } + )"; char const* natspec = "{" "\"methods\":{" @@ -264,26 +279,27 @@ BOOST_AUTO_TEST_CASE(dev_mutiline_param_description) BOOST_AUTO_TEST_CASE(dev_multiple_functions) { - char const* sourceCode = "contract test {\n" - " /// @dev Multiplies a number by 7 and adds second parameter\n" - " /// @param a Documentation for the first parameter\n" - " /// @param second Documentation for the second parameter\n" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" - " \n" - " /// @dev Divides 2 numbers\n" - " /// @param input Documentation for the input parameter\n" - " /// @param div Documentation for the div parameter\n" - " function divide(uint input, uint div) returns(uint d)\n" - " {\n" - " return input / div;\n" - " }\n" - " /// @dev Subtracts 3 from `input`\n" - " /// @param input Documentation for the input parameter\n" - " function sub(int input) returns(int d)\n" - " {\n" - " return input - 3;\n" - " }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /// @dev Multiplies a number by 7 and adds second parameter + /// @param a Documentation for the first parameter + /// @param second Documentation for the second parameter + function mul(uint a, uint second) returns(uint d) { + return a * 7 + second; + } + /// @dev Divides 2 numbers + /// @param input Documentation for the input parameter + /// @param div Documentation for the div parameter + function divide(uint input, uint div) returns(uint d) { + return input / div; + } + /// @dev Subtracts 3 from `input` + /// @param input Documentation for the input parameter + function sub(int input) returns(int d) { + return input - 3; + } + } + )"; char const* natspec = "{" "\"methods\":{" @@ -314,14 +330,16 @@ BOOST_AUTO_TEST_CASE(dev_multiple_functions) BOOST_AUTO_TEST_CASE(dev_return) { - char const* sourceCode = "contract test {\n" - " /// @dev Multiplies a number by 7 and adds second parameter\n" - " /// @param a Documentation for the first parameter starts here.\n" - " /// Since it's a really complicated parameter we need 2 lines\n" - " /// @param second Documentation for the second parameter\n" - " /// @return The result of the multiplication\n" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /// @dev Multiplies a number by 7 and adds second parameter + /// @param a Documentation for the first parameter starts here. + /// Since it's a really complicated parameter we need 2 lines + /// @param second Documentation for the second parameter + /// @return The result of the multiplication + function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + } + )"; char const* natspec = "{" "\"methods\":{" @@ -339,15 +357,19 @@ BOOST_AUTO_TEST_CASE(dev_return) } BOOST_AUTO_TEST_CASE(dev_return_desc_after_nl) { - char const* sourceCode = "contract test {\n" - " /// @dev Multiplies a number by 7 and adds second parameter\n" - " /// @param a Documentation for the first parameter starts here.\n" - " /// Since it's a really complicated parameter we need 2 lines\n" - " /// @param second Documentation for the second parameter\n" - " /// @return\n" - " /// The result of the multiplication\n" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /// @dev Multiplies a number by 7 and adds second parameter + /// @param a Documentation for the first parameter starts here. + /// Since it's a really complicated parameter we need 2 lines + /// @param second Documentation for the second parameter + /// @return + /// The result of the multiplication + function mul(uint a, uint second) returns(uint d) { + return a * 7 + second; + } + } + )"; char const* natspec = "{" "\"methods\":{" @@ -367,15 +389,19 @@ BOOST_AUTO_TEST_CASE(dev_return_desc_after_nl) BOOST_AUTO_TEST_CASE(dev_multiline_return) { - char const* sourceCode = "contract test {\n" - " /// @dev Multiplies a number by 7 and adds second parameter\n" - " /// @param a Documentation for the first parameter starts here.\n" - " /// Since it's a really complicated parameter we need 2 lines\n" - " /// @param second Documentation for the second parameter\n" - " /// @return The result of the multiplication\n" - " /// and cookies with nutella\n" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /// @dev Multiplies a number by 7 and adds second parameter + /// @param a Documentation for the first parameter starts here. + /// Since it's a really complicated parameter we need 2 lines + /// @param second Documentation for the second parameter + /// @return The result of the multiplication + /// and cookies with nutella + function mul(uint a, uint second) returns(uint d) { + return a * 7 + second; + } + } + )"; char const* natspec = "{" "\"methods\":{" @@ -394,17 +420,21 @@ BOOST_AUTO_TEST_CASE(dev_multiline_return) BOOST_AUTO_TEST_CASE(dev_multiline_comment) { - char const* sourceCode = "contract test {\n" - " /**\n" - " * @dev Multiplies a number by 7 and adds second parameter\n" - " * @param a Documentation for the first parameter starts here.\n" - " * Since it's a really complicated parameter we need 2 lines\n" - " * @param second Documentation for the second parameter\n" - " * @return The result of the multiplication\n" - " * and cookies with nutella\n" - " */" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /** + * @dev Multiplies a number by 7 and adds second parameter + * @param a Documentation for the first parameter starts here. + * Since it's a really complicated parameter we need 2 lines + * @param second Documentation for the second parameter + * @return The result of the multiplication + * and cookies with nutella + */ + function mul(uint a, uint second) returns(uint d) { + return a * 7 + second; + } + } + )"; char const* natspec = "{" "\"methods\":{" @@ -423,10 +453,12 @@ BOOST_AUTO_TEST_CASE(dev_multiline_comment) BOOST_AUTO_TEST_CASE(dev_contract_no_doc) { - char const* sourceCode = "contract test {\n" - " /// @dev Mul function\n" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /// @dev Mul function + function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + } + )"; char const* natspec = "{" " \"methods\":{" @@ -441,12 +473,14 @@ BOOST_AUTO_TEST_CASE(dev_contract_no_doc) BOOST_AUTO_TEST_CASE(dev_contract_doc) { - char const* sourceCode = " /// @author Lefteris\n" - " /// @title Just a test contract\n" - "contract test {\n" - " /// @dev Mul function\n" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" - "}\n"; + char const* sourceCode = R"( + /// @author Lefteris + /// @title Just a test contract + contract test { + /// @dev Mul function + function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + } + )"; char const* natspec = "{" " \"author\": \"Lefteris\"," @@ -463,13 +497,15 @@ BOOST_AUTO_TEST_CASE(dev_contract_doc) BOOST_AUTO_TEST_CASE(dev_author_at_function) { - char const* sourceCode = " /// @author Lefteris\n" - " /// @title Just a test contract\n" - "contract test {\n" - " /// @dev Mul function\n" - " /// @author John Doe\n" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" - "}\n"; + char const* sourceCode = R"( + /// @author Lefteris + /// @title Just a test contract + contract test { + /// @dev Mul function + /// @author John Doe + function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + } + )"; char const* natspec = "{" " \"author\": \"Lefteris\"," @@ -549,25 +585,29 @@ BOOST_AUTO_TEST_CASE(empty_comment) BOOST_AUTO_TEST_CASE(dev_title_at_function_error) { - char const* sourceCode = " /// @author Lefteris\n" - " /// @title Just a test contract\n" - "contract test {\n" - " /// @dev Mul function\n" - " /// @title I really should not be here\n" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" - "}\n"; + char const* sourceCode = R"( + /// @author Lefteris + /// @title Just a test contract + contract test { + /// @dev Mul function + /// @title I really should not be here + function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + } + )"; expectNatspecError(sourceCode); } -BOOST_AUTO_TEST_CASE(dev_documenting_nonexistant_param) +BOOST_AUTO_TEST_CASE(dev_documenting_nonexistent_param) { - char const* sourceCode = "contract test {\n" - " /// @dev Multiplies a number by 7 and adds second parameter\n" - " /// @param a Documentation for the first parameter\n" - " /// @param not_existing Documentation for the second parameter\n" - " function mul(uint a, uint second) returns(uint d) { return a * 7 + second; }\n" - "}\n"; + char const* sourceCode = R"( + contract test { + /// @dev Multiplies a number by 7 and adds second parameter + /// @param a Documentation for the first parameter + /// @param not_existing Documentation for the second parameter + function mul(uint a, uint second) returns(uint d) { return a * 7 + second; } + } + )"; expectNatspecError(sourceCode); } diff --git a/test/libsolidity/SolidityOptimizer.cpp b/test/libsolidity/SolidityOptimizer.cpp index 017fc0e9..2e2e0c6c 100644 --- a/test/libsolidity/SolidityOptimizer.cpp +++ b/test/libsolidity/SolidityOptimizer.cpp @@ -1,18 +1,18 @@ /* - This file is part of cpp-ethereum. + This file is part of solidity. - cpp-ethereum is free software: you can redistribute it and/or modify + 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. - cpp-ethereum is distributed in the hope that it will be useful, + 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. + along with solidity. If not, see <http://www.gnu.org/licenses/>. */ /** * @author Christian <c@ethdev.com> @@ -20,19 +20,24 @@ * Tests for the Solidity optimizer. */ -#include <string> -#include <tuple> -#include <memory> -#include <boost/test/unit_test.hpp> -#include <boost/lexical_cast.hpp> #include <test/libsolidity/SolidityExecutionFramework.h> + #include <libevmasm/CommonSubexpressionEliminator.h> +#include <libevmasm/PeepholeOptimiser.h> #include <libevmasm/ControlFlowGraph.h> #include <libevmasm/Assembly.h> #include <libevmasm/BlockDeduplicator.h> +#include <boost/test/unit_test.hpp> +#include <boost/lexical_cast.hpp> + +#include <string> +#include <tuple> +#include <memory> + using namespace std; using namespace dev::eth; +using namespace dev::test; namespace dev { @@ -41,10 +46,29 @@ namespace solidity namespace test { -class OptimizerTestFramework: public ExecutionFramework +class OptimizerTestFramework: public SolidityExecutionFramework { public: OptimizerTestFramework() { } + + bytes const& compileAndRunWithOptimizer( + std::string const& _sourceCode, + u256 const& _value = 0, + std::string const& _contractName = "", + bool const _optimize = true, + unsigned const _optimizeRuns = 200 + ) + { + bool const c_optimize = m_optimize; + unsigned const c_optimizeRuns = m_optimizeRuns; + m_optimize = _optimize; + m_optimizeRuns = _optimizeRuns; + bytes const& ret = compileAndRun(_sourceCode, _value, _contractName); + m_optimize = c_optimize; + m_optimizeRuns = c_optimizeRuns; + return ret; + } + /// Compiles the source code with and without optimizing. void compileBothVersions( std::string const& _sourceCode, @@ -52,22 +76,16 @@ public: std::string const& _contractName = "" ) { - m_optimize = false; - bytes nonOptimizedBytecode = compileAndRun(_sourceCode, _value, _contractName); + bytes nonOptimizedBytecode = compileAndRunWithOptimizer(_sourceCode, _value, _contractName, false); m_nonOptimizedContract = m_contractAddress; - m_optimize = true; - bytes optimizedBytecode = compileAndRun(_sourceCode, _value, _contractName); - size_t nonOptimizedSize = 0; - solidity::eachInstruction(nonOptimizedBytecode, [&](Instruction, u256 const&) { - nonOptimizedSize++; - }); - size_t optimizedSize = 0; - solidity::eachInstruction(optimizedBytecode, [&](Instruction, u256 const&) { - optimizedSize++; - }); + bytes optimizedBytecode = compileAndRunWithOptimizer(_sourceCode, _value, _contractName, true); + size_t nonOptimizedSize = numInstructions(nonOptimizedBytecode); + size_t optimizedSize = numInstructions(optimizedBytecode); BOOST_CHECK_MESSAGE( - nonOptimizedSize > optimizedSize, - "Optimizer did not reduce bytecode size." + optimizedSize < nonOptimizedSize, + string("Optimizer did not reduce bytecode size. Non-optimized size: ") + + std::to_string(nonOptimizedSize) + " - optimized size: " + + std::to_string(optimizedSize) ); m_optimizedContract = m_contractAddress; } @@ -151,6 +169,22 @@ public: } protected: + /// @returns the number of intructions in the given bytecode, not taking the metadata hash + /// into account. + size_t numInstructions(bytes const& _bytecode) + { + BOOST_REQUIRE(_bytecode.size() > 5); + size_t metadataSize = (_bytecode[_bytecode.size() - 2] << 8) + _bytecode[_bytecode.size() - 1]; + BOOST_REQUIRE_MESSAGE(metadataSize == 0x29, "Invalid metadata size"); + BOOST_REQUIRE(_bytecode.size() >= metadataSize + 2); + bytes realCode = bytes(_bytecode.begin(), _bytecode.end() - metadataSize - 2); + size_t instructions = 0; + solidity::eachInstruction(realCode, [&](Instruction, u256 const&) { + instructions++; + }); + return instructions; + } + Address m_optimizedContract; Address m_nonOptimizedContract; }; @@ -310,8 +344,7 @@ BOOST_AUTO_TEST_CASE(retain_information_in_branches) compareVersions("f(uint256,bytes32)", 8, "def"); compareVersions("f(uint256,bytes32)", 10, "ghi"); - m_optimize = true; - bytes optimizedBytecode = compileAndRun(sourceCode, 0, "c"); + bytes optimizedBytecode = compileAndRunWithOptimizer(sourceCode, 0, "c", true); size_t numSHA3s = 0; eachInstruction(optimizedBytecode, [&](Instruction _instr, u256 const&) { if (_instr == Instruction::SHA3) @@ -354,8 +387,7 @@ BOOST_AUTO_TEST_CASE(store_tags_as_unions) compileBothVersions(sourceCode); compareVersions("f(uint256,bytes32)", 7, "abc"); - m_optimize = true; - bytes optimizedBytecode = compileAndRun(sourceCode, 0, "test"); + bytes optimizedBytecode = compileAndRunWithOptimizer(sourceCode, 0, "test", true); size_t numSHA3s = 0; eachInstruction(optimizedBytecode, [&](Instruction _instr, u256 const&) { if (_instr == Instruction::SHA3) @@ -1121,6 +1153,40 @@ BOOST_AUTO_TEST_CASE(block_deduplicator_loops) BOOST_CHECK_EQUAL(pushTags.size(), 1); } +BOOST_AUTO_TEST_CASE(clear_unreachable_code) +{ + AssemblyItems items{ + AssemblyItem(PushTag, 1), + Instruction::JUMP, + u256(0), + Instruction::SLOAD, + AssemblyItem(Tag, 2), + u256(5), + u256(6), + Instruction::SSTORE, + AssemblyItem(PushTag, 1), + Instruction::JUMP, + u256(5), + u256(6) + }; + AssemblyItems expectation{ + AssemblyItem(PushTag, 1), + Instruction::JUMP, + AssemblyItem(Tag, 2), + u256(5), + u256(6), + Instruction::SSTORE, + AssemblyItem(PushTag, 1), + Instruction::JUMP + }; + PeepholeOptimiser peepOpt(items); + BOOST_REQUIRE(peepOpt.optimise()); + BOOST_CHECK_EQUAL_COLLECTIONS( + items.begin(), items.end(), + expectation.begin(), expectation.end() + ); +} + BOOST_AUTO_TEST_CASE(computing_constants) { char const* sourceCode = R"( @@ -1148,9 +1214,7 @@ BOOST_AUTO_TEST_CASE(computing_constants) compareVersions("set()"); compareVersions("get()"); - m_optimize = true; - m_optimizeRuns = 1; - bytes optimizedBytecode = compileAndRun(sourceCode, 0, "c"); + bytes optimizedBytecode = compileAndRunWithOptimizer(sourceCode, 0, "c", true, 1); bytes complicatedConstant = toBigEndian(u256("0x817416927846239487123469187231298734162934871263941234127518276")); unsigned occurrences = 0; for (auto iter = optimizedBytecode.cbegin(); iter < optimizedBytecode.cend(); ++occurrences) @@ -1266,6 +1330,29 @@ BOOST_AUTO_TEST_CASE(invalid_state_at_control_flow_join) compareVersions("test()"); } +BOOST_AUTO_TEST_CASE(cse_sub_zero) +{ + checkCSE({ + u256(0), + Instruction::DUP2, + Instruction::SUB + }, { + Instruction::DUP1 + }); + + checkCSE({ + Instruction::DUP1, + u256(0), + Instruction::SUB + }, { + u256(0), + Instruction::DUP2, + Instruction::SWAP1, + Instruction::SUB + }); +} + + BOOST_AUTO_TEST_SUITE_END() } diff --git a/test/libsolidity/SolidityParser.cpp b/test/libsolidity/SolidityParser.cpp index 914dbc30..a3bfab75 100644 --- a/test/libsolidity/SolidityParser.cpp +++ b/test/libsolidity/SolidityParser.cpp @@ -1,18 +1,18 @@ /* - This file is part of cpp-ethereum. + This file is part of solidity. - cpp-ethereum is free software: you can redistribute it and/or modify + 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. - cpp-ethereum is distributed in the hope that it will be useful, + 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. + along with solidity. If not, see <http://www.gnu.org/licenses/>. */ /** * @author Christian <c@ethdev.com> @@ -26,6 +26,7 @@ #include <libsolidity/parsing/Parser.h> #include <libsolidity/interface/Exceptions.h> #include "../TestHelper.h" +#include "ErrorCheck.h" using namespace std; @@ -71,6 +72,22 @@ bool successParse(std::string const& _source) return true; } +Error getError(std::string const& _source) +{ + ErrorList errors; + try + { + parseText(_source, errors); + } + catch (FatalError const& /*_exception*/) + { + // no-op + } + Error const* error = Error::containsErrorOfType(errors, Error::Type::ParserError); + BOOST_REQUIRE(error); + return *error; +} + void checkFunctionNatspec( FunctionDefinition const* _function, std::string const& _expectedDoc @@ -83,78 +100,102 @@ void checkFunctionNatspec( } +#define CHECK_PARSE_ERROR(source, substring) \ +do \ +{\ + Error err = getError((source)); \ + BOOST_CHECK(searchErrorMessage(err, (substring))); \ +}\ +while(0) + BOOST_AUTO_TEST_SUITE(SolidityParser) BOOST_AUTO_TEST_CASE(smoke_test) { - char const* text = "contract test {\n" - " uint256 stateVariable1;\n" - "}\n"; + char const* text = R"( + contract test { + uint256 stateVariable1; + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(missing_variable_name_in_declaration) { - char const* text = "contract test {\n" - " uint256 ;\n" - "}\n"; - BOOST_CHECK(!successParse(text)); + char const* text = R"( + contract test { + uint256 ; + } + )"; + CHECK_PARSE_ERROR(text, "Expected identifier"); } BOOST_AUTO_TEST_CASE(empty_function) { - char const* text = "contract test {\n" - " uint256 stateVar;\n" - " function functionName(bytes20 arg1, address addr) constant\n" - " returns (int id)\n" - " { }\n" - "}\n"; + char const* text = R"( + contract test { + uint256 stateVar; + function functionName(bytes20 arg1, address addr) constant + returns (int id) + { } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(no_function_params) { - char const* text = "contract test {\n" - " uint256 stateVar;\n" - " function functionName() {}\n" - "}\n"; + char const* text = R"( + contract test { + uint256 stateVar; + function functionName() {} + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(single_function_param) { - char const* text = "contract test {\n" - " uint256 stateVar;\n" - " function functionName(bytes32 input) returns (bytes32 out) {}\n" - "}\n"; + char const* text = R"( + contract test { + uint256 stateVar; + function functionName(bytes32 input) returns (bytes32 out) {} + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(function_no_body) { - char const* text = "contract test {\n" - " function functionName(bytes32 input) returns (bytes32 out);\n" - "}\n"; + char const* text = R"( + contract test { + function functionName(bytes32 input) returns (bytes32 out); + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(missing_parameter_name_in_named_args) { - char const* text = "contract test {\n" - " function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; }\n" - " function b() returns (uint r) { r = a({: 1, : 2, : 3}); }\n" - "}\n"; - BOOST_CHECK(!successParse(text)); + char const* text = R"( + contract test { + function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; } + function b() returns (uint r) { r = a({: 1, : 2, : 3}); } + } + )"; + CHECK_PARSE_ERROR(text, "Expected identifier"); } BOOST_AUTO_TEST_CASE(missing_argument_in_named_args) { - char const* text = "contract test {\n" - " function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; }\n" - " function b() returns (uint r) { r = a({a: , b: , c: }); }\n" - "}\n"; - BOOST_CHECK(!successParse(text)); + char const* text = R"( + contract test { + function a(uint a, uint b, uint c) returns (uint r) { r = a * 100 + b * 10 + c * 1; } + function b() returns (uint r) { r = a({a: , b: , c: }); } + } + )"; + CHECK_PARSE_ERROR(text, "Expected primary expression"); } BOOST_AUTO_TEST_CASE(two_exact_functions) @@ -184,11 +225,13 @@ BOOST_AUTO_TEST_CASE(overloaded_functions) BOOST_AUTO_TEST_CASE(function_natspec_documentation) { - char const* text = "contract test {\n" - " uint256 stateVar;\n" - " /// This is a test function\n" - " function functionName(bytes32 input) returns (bytes32 out) {}\n" - "}\n"; + char const* text = R"( + contract test { + uint256 stateVar; + /// This is a test function + function functionName(bytes32 input) returns (bytes32 out) {} + } + )"; BOOST_CHECK(successParse(text)); ErrorList errors; ASTPointer<ContractDefinition> contract = parseText(text, errors); @@ -202,11 +245,13 @@ BOOST_AUTO_TEST_CASE(function_natspec_documentation) BOOST_AUTO_TEST_CASE(function_normal_comments) { FunctionDefinition const* function = nullptr; - char const* text = "contract test {\n" - " uint256 stateVar;\n" - " // We won't see this comment\n" - " function functionName(bytes32 input) returns (bytes32 out) {}\n" - "}\n"; + char const* text = R"( + contract test { + uint256 stateVar; + // We won't see this comment + function functionName(bytes32 input) returns (bytes32 out) {} + } + )"; BOOST_CHECK(successParse(text)); ErrorList errors; ASTPointer<ContractDefinition> contract = parseText(text, errors); @@ -219,17 +264,19 @@ BOOST_AUTO_TEST_CASE(function_normal_comments) BOOST_AUTO_TEST_CASE(multiple_functions_natspec_documentation) { FunctionDefinition const* function = nullptr; - char const* text = "contract test {\n" - " uint256 stateVar;\n" - " /// This is test function 1\n" - " function functionName1(bytes32 input) returns (bytes32 out) {}\n" - " /// This is test function 2\n" - " function functionName2(bytes32 input) returns (bytes32 out) {}\n" - " // nothing to see here\n" - " function functionName3(bytes32 input) returns (bytes32 out) {}\n" - " /// This is test function 4\n" - " function functionName4(bytes32 input) returns (bytes32 out) {}\n" - "}\n"; + char const* text = R"( + contract test { + uint256 stateVar; + /// This is test function 1 + function functionName1(bytes32 input) returns (bytes32 out) {} + /// This is test function 2 + function functionName2(bytes32 input) returns (bytes32 out) {} + // nothing to see here + function functionName3(bytes32 input) returns (bytes32 out) {} + /// This is test function 4 + function functionName4(bytes32 input) returns (bytes32 out) {} + } + )"; BOOST_CHECK(successParse(text)); ErrorList errors; ASTPointer<ContractDefinition> contract = parseText(text, errors); @@ -252,12 +299,14 @@ BOOST_AUTO_TEST_CASE(multiple_functions_natspec_documentation) BOOST_AUTO_TEST_CASE(multiline_function_documentation) { FunctionDefinition const* function = nullptr; - char const* text = "contract test {\n" - " uint256 stateVar;\n" - " /// This is a test function\n" - " /// and it has 2 lines\n" - " function functionName1(bytes32 input) returns (bytes32 out) {}\n" - "}\n"; + char const* text = R"( + contract test { + uint256 stateVar; + /// This is a test function + /// and it has 2 lines + function functionName1(bytes32 input) returns (bytes32 out) {} + } + )"; BOOST_CHECK(successParse(text)); ErrorList errors; ASTPointer<ContractDefinition> contract = parseText(text, errors); @@ -270,19 +319,21 @@ BOOST_AUTO_TEST_CASE(multiline_function_documentation) BOOST_AUTO_TEST_CASE(natspec_comment_in_function_body) { FunctionDefinition const* function = nullptr; - char const* text = "contract test {\n" - " /// fun1 description\n" - " function fun1(uint256 a) {\n" - " var b;\n" - " /// I should not interfere with actual natspec comments\n" - " uint256 c;\n" - " mapping(address=>bytes32) d;\n" - " bytes7 name = \"Solidity\";" - " }\n" - " /// This is a test function\n" - " /// and it has 2 lines\n" - " function fun(bytes32 input) returns (bytes32 out) {}\n" - "}\n"; + char const* text = R"( + contract test { + /// fun1 description + function fun1(uint256 a) { + var b; + /// I should not interfere with actual natspec comments + uint256 c; + mapping(address=>bytes32) d; + bytes7 name = "Solidity"; + } + /// This is a test function + /// and it has 2 lines + function fun(bytes32 input) returns (bytes32 out) {} + } + )"; BOOST_CHECK(successParse(text)); ErrorList errors; ASTPointer<ContractDefinition> contract = parseText(text, errors); @@ -299,17 +350,19 @@ BOOST_AUTO_TEST_CASE(natspec_comment_in_function_body) BOOST_AUTO_TEST_CASE(natspec_docstring_between_keyword_and_signature) { FunctionDefinition const* function = nullptr; - char const* text = "contract test {\n" - " uint256 stateVar;\n" - " function ///I am in the wrong place \n" - " fun1(uint256 a) {\n" - " var b;\n" - " /// I should not interfere with actual natspec comments\n" - " uint256 c;\n" - " mapping(address=>bytes32) d;\n" - " bytes7 name = \"Solidity\";" - " }\n" - "}\n"; + char const* text = R"( + contract test { + uint256 stateVar; + function ///I am in the wrong place + fun1(uint256 a) { + var b; + /// I should not interfere with actual natspec comments + uint256 c; + mapping(address=>bytes32) d; + bytes7 name = "Solidity"; + } + } + )"; BOOST_CHECK(successParse(text)); ErrorList errors; ASTPointer<ContractDefinition> contract = parseText(text, errors); @@ -323,17 +376,19 @@ BOOST_AUTO_TEST_CASE(natspec_docstring_between_keyword_and_signature) BOOST_AUTO_TEST_CASE(natspec_docstring_after_signature) { FunctionDefinition const* function = nullptr; - char const* text = "contract test {\n" - " uint256 stateVar;\n" - " function fun1(uint256 a) {\n" - " /// I should have been above the function signature\n" - " var b;\n" - " /// I should not interfere with actual natspec comments\n" - " uint256 c;\n" - " mapping(address=>bytes32) d;\n" - " bytes7 name = \"Solidity\";" - " }\n" - "}\n"; + char const* text = R"( + contract test { + uint256 stateVar; + function fun1(uint256 a) { + /// I should have been above the function signature + var b; + /// I should not interfere with actual natspec comments + uint256 c; + mapping(address=>bytes32) d; + bytes7 name = "Solidity"; + } + } + )"; BOOST_CHECK(successParse(text)); ErrorList errors; ASTPointer<ContractDefinition> contract = parseText(text, errors); @@ -346,71 +401,83 @@ BOOST_AUTO_TEST_CASE(natspec_docstring_after_signature) BOOST_AUTO_TEST_CASE(struct_definition) { - char const* text = "contract test {\n" - " uint256 stateVar;\n" - " struct MyStructName {\n" - " address addr;\n" - " uint256 count;\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + uint256 stateVar; + struct MyStructName { + address addr; + uint256 count; + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(mapping) { - char const* text = "contract test {\n" - " mapping(address => bytes32) names;\n" - "}\n"; + char const* text = R"( + contract test { + mapping(address => bytes32) names; + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(mapping_in_struct) { - char const* text = "contract test {\n" - " struct test_struct {\n" - " address addr;\n" - " uint256 count;\n" - " mapping(bytes32 => test_struct) self_reference;\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + struct test_struct { + address addr; + uint256 count; + mapping(bytes32 => test_struct) self_reference; + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(mapping_to_mapping_in_struct) { - char const* text = "contract test {\n" - " struct test_struct {\n" - " address addr;\n" - " mapping (uint64 => mapping (bytes32 => uint)) complex_mapping;\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + struct test_struct { + address addr; + mapping (uint64 => mapping (bytes32 => uint)) complex_mapping; + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(variable_definition) { - char const* text = "contract test {\n" - " function fun(uint256 a) {\n" - " var b;\n" - " uint256 c;\n" - " mapping(address=>bytes32) d;\n" - " customtype varname;\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun(uint256 a) { + var b; + uint256 c; + mapping(address=>bytes32) d; + customtype varname; + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(variable_definition_with_initialization) { - char const* text = "contract test {\n" - " function fun(uint256 a) {\n" - " var b = 2;\n" - " uint256 c = 0x87;\n" - " mapping(address=>bytes32) d;\n" - " bytes7 name = \"Solidity\";" - " customtype varname;\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun(uint256 a) { + var b = 2; + uint256 c = 0x87; + mapping(address=>bytes32) d; + bytes7 name = "Solidity"; + customtype varname; + } + } + )"; BOOST_CHECK(successParse(text)); } @@ -421,7 +488,7 @@ BOOST_AUTO_TEST_CASE(variable_definition_in_function_parameter) function fun(var a) {} } )"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected explicit type name"); } BOOST_AUTO_TEST_CASE(variable_definition_in_mapping) @@ -433,7 +500,7 @@ BOOST_AUTO_TEST_CASE(variable_definition_in_mapping) } } )"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected elementary type name for mapping key type"); } BOOST_AUTO_TEST_CASE(variable_definition_in_function_return) @@ -445,26 +512,30 @@ BOOST_AUTO_TEST_CASE(variable_definition_in_function_return) } } )"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected explicit type name"); } BOOST_AUTO_TEST_CASE(operator_expression) { - char const* text = "contract test {\n" - " function fun(uint256 a) {\n" - " uint256 x = (1 + 4) || false && (1 - 12) + -9;\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun(uint256 a) { + uint256 x = (1 + 4) || false && (1 - 12) + -9; + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(complex_expression) { - char const* text = "contract test {\n" - " function fun(uint256 a) {\n" - " uint256 x = (1 + 4).member(++67)[a/=9] || true;\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun(uint256 a) { + uint256 x = (1 + 4).member(++67)[a/=9] || true; + } + } + )"; BOOST_CHECK(successParse(text)); } @@ -475,248 +546,294 @@ BOOST_AUTO_TEST_CASE(exp_expression) function fun(uint256 a) { uint256 x = 3 ** a; } - })"; + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(while_loop) { - char const* text = "contract test {\n" - " function fun(uint256 a) {\n" - " while (true) { uint256 x = 1; break; continue; } x = 9;\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun(uint256 a) { + while (true) { uint256 x = 1; break; continue; } x = 9; + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(for_loop_vardef_initexpr) { - char const* text = "contract test {\n" - " function fun(uint256 a) {\n" - " for (uint256 i = 0; i < 10; i++)\n" - " { uint256 x = i; break; continue; }\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun(uint256 a) { + for (uint256 i = 0; i < 10; i++) { + uint256 x = i; break; continue; + } + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(for_loop_simple_initexpr) { - char const* text = "contract test {\n" - " function fun(uint256 a) {\n" - " uint256 i =0;\n" - " for (i = 0; i < 10; i++)\n" - " { uint256 x = i; break; continue; }\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun(uint256 a) { + uint256 i =0; + for (i = 0; i < 10; i++) { + uint256 x = i; break; continue; + } + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(for_loop_simple_noexpr) { - char const* text = "contract test {\n" - " function fun(uint256 a) {\n" - " uint256 i =0;\n" - " for (;;)\n" - " { uint256 x = i; break; continue; }\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun(uint256 a) { + uint256 i =0; + for (;;) { + uint256 x = i; break; continue; + } + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(for_loop_single_stmt_body) { - char const* text = "contract test {\n" - " function fun(uint256 a) {\n" - " uint256 i =0;\n" - " for (i = 0; i < 10; i++)\n" - " continue;\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun(uint256 a) { + uint256 i = 0; + for (i = 0; i < 10; i++) + continue; + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(if_statement) { - char const* text = "contract test {\n" - " function fun(uint256 a) {\n" - " if (a >= 8) { return 2; } else { var b = 7; }\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun(uint256 a) { + if (a >= 8) { return 2; } else { var b = 7; } + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(else_if_statement) { - char const* text = "contract test {\n" - " function fun(uint256 a) returns (address b) {\n" - " if (a < 0) b = 0x67; else if (a == 0) b = 0x12; else b = 0x78;\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun(uint256 a) returns (address b) { + if (a < 0) b = 0x67; else if (a == 0) b = 0x12; else b = 0x78; + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(statement_starting_with_type_conversion) { - char const* text = "contract test {\n" - " function fun() {\n" - " uint64(2);\n" - " uint64[7](3);\n" - " uint64[](3);\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun() { + uint64(2); + uint64[7](3); + uint64[](3); + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(type_conversion_to_dynamic_array) { - char const* text = "contract test {\n" - " function fun() {\n" - " var x = uint64[](3);\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun() { + var x = uint64[](3); + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(import_directive) { - char const* text = "import \"abc\";\n" - "contract test {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "}\n"; + char const* text = R"( + import "abc"; + contract test { + function fun() { + uint64(2); + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(multiple_contracts) { - char const* text = "contract test {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "}\n" - "contract test2 {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "}\n"; + char const* text = R"( + contract test { + function fun() { + uint64(2); + } + } + contract test2 { + function fun() { + uint64(2); + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(multiple_contracts_and_imports) { - char const* text = "import \"abc\";\n" - "contract test {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "}\n" - "import \"def\";\n" - "contract test2 {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "}\n" - "import \"ghi\";\n"; + char const* text = R"( + import "abc"; + contract test { + function fun() { + uint64(2); + } + } + import "def"; + contract test2 { + function fun() { + uint64(2); + } + } + import "ghi"; + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(contract_inheritance) { - char const* text = "contract base {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "}\n" - "contract derived is base {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "}\n"; + char const* text = R"( + contract base { + function fun() { + uint64(2); + } + } + contract derived is base { + function fun() { + uint64(2); + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(contract_multiple_inheritance) { - char const* text = "contract base {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "}\n" - "contract derived is base, nonExisting {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "}\n"; + char const* text = R"( + contract base { + function fun() { + uint64(2); + } + } + contract derived is base, nonExisting { + function fun() { + uint64(2); + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(contract_multiple_inheritance_with_arguments) { - char const* text = "contract base {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "}\n" - "contract derived is base(2), nonExisting(\"abc\", \"def\", base.fun()) {\n" - " function fun() {\n" - " uint64(2);\n" - " }\n" - "}\n"; + char const* text = R"( + contract base { + function fun() { + uint64(2); + } + } + contract derived is base(2), nonExisting("abc", "def", base.fun()) { + function fun() { + uint64(2); + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(placeholder_in_function_context) { - char const* text = "contract c {\n" - " function fun() returns (uint r) {\n" - " var _ = 8;\n" - " return _ + 1;" - " }\n" - "}\n"; + char const* text = R"( + contract c { + function fun() returns (uint r) { + var _ = 8; + return _ + 1; + } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(modifier) { - char const* text = "contract c {\n" - " modifier mod { if (msg.sender == 0) _; }\n" - "}\n"; + char const* text = R"( + contract c { + modifier mod { if (msg.sender == 0) _; } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(modifier_without_semicolon) { - char const* text = "contract c {\n" - " modifier mod { if (msg.sender == 0) _ }\n" - "}\n"; - BOOST_CHECK(!successParse(text)); + char const* text = R"( + contract c { + modifier mod { if (msg.sender == 0) _ } + } + )"; + CHECK_PARSE_ERROR(text, "Expected token Semicolon got"); } BOOST_AUTO_TEST_CASE(modifier_arguments) { - char const* text = "contract c {\n" - " modifier mod(uint a) { if (msg.sender == a) _; }\n" - "}\n"; + char const* text = R"( + contract c { + modifier mod(address a) { if (msg.sender == a) _; } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(modifier_invocation) { - char const* text = "contract c {\n" - " modifier mod1(uint a) { if (msg.sender == a) _; }\n" - " modifier mod2 { if (msg.sender == 2) _; }\n" - " function f() mod1(7) mod2 { }\n" - "}\n"; + char const* text = R"( + contract c { + modifier mod1(uint a) { if (msg.sender == a) _; } + modifier mod2 { if (msg.sender == 2) _; } + function f() mod1(7) mod2 { } + } + )"; BOOST_CHECK(successParse(text)); } BOOST_AUTO_TEST_CASE(fallback_function) { - char const* text = "contract c {\n" - " function() { }\n" - "}\n"; + char const* text = R"( + contract c { + function() { } + } + )"; BOOST_CHECK(successParse(text)); } @@ -769,7 +886,7 @@ BOOST_AUTO_TEST_CASE(multiple_visibility_specifiers) contract c { uint private internal a; })"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Visibility already specified"); } BOOST_AUTO_TEST_CASE(literal_constants_with_ether_subdenominations) @@ -824,7 +941,7 @@ BOOST_AUTO_TEST_CASE(empty_enum_declaration) contract c { enum foo { } })"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "enum with no members is not allowed"); } BOOST_AUTO_TEST_CASE(malformed_enum_declaration) @@ -833,7 +950,7 @@ BOOST_AUTO_TEST_CASE(malformed_enum_declaration) contract c { enum foo { WARNING,} })"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected Identifier after"); } BOOST_AUTO_TEST_CASE(external_function) @@ -851,7 +968,7 @@ BOOST_AUTO_TEST_CASE(external_variable) contract c { uint external x; })"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected identifier"); } BOOST_AUTO_TEST_CASE(arrays_in_storage) @@ -899,7 +1016,7 @@ BOOST_AUTO_TEST_CASE(constant_is_keyword) contract Foo { uint constant = 4; })"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected identifier"); } BOOST_AUTO_TEST_CASE(var_array) @@ -908,7 +1025,7 @@ BOOST_AUTO_TEST_CASE(var_array) contract Foo { function f() { var[] a; } })"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected identifier"); } BOOST_AUTO_TEST_CASE(location_specifiers_for_params) @@ -940,7 +1057,7 @@ BOOST_AUTO_TEST_CASE(location_specifiers_for_state) contract Foo { uint[] memory x; })"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected identifier"); } BOOST_AUTO_TEST_CASE(location_specifiers_with_var) @@ -949,7 +1066,7 @@ BOOST_AUTO_TEST_CASE(location_specifiers_with_var) contract Foo { function f() { var memory x; } })"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Location specifier needs explicit type name"); } BOOST_AUTO_TEST_CASE(empty_comment) @@ -962,6 +1079,19 @@ BOOST_AUTO_TEST_CASE(empty_comment) BOOST_CHECK(successParse(text)); } +BOOST_AUTO_TEST_CASE(comment_end_with_double_star) +{ + char const* text = R"( + contract C1 { + /** + **/ + } + contract C2 {} + )"; + BOOST_CHECK(successParse(text)); +} + + BOOST_AUTO_TEST_CASE(library_simple) { char const* text = R"( @@ -983,7 +1113,7 @@ BOOST_AUTO_TEST_CASE(local_const_variable) return local; } })"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected token Semicolon"); } BOOST_AUTO_TEST_CASE(multi_variable_declaration) @@ -1102,7 +1232,7 @@ BOOST_AUTO_TEST_CASE(inline_array_empty_cells_check_lvalue) } } )"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected expression"); } BOOST_AUTO_TEST_CASE(inline_array_empty_cells_check_without_lvalue) @@ -1115,7 +1245,7 @@ BOOST_AUTO_TEST_CASE(inline_array_empty_cells_check_without_lvalue) } } )"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected expression"); } BOOST_AUTO_TEST_CASE(conditional_true_false_literal) @@ -1216,7 +1346,7 @@ BOOST_AUTO_TEST_CASE(no_double_radix_in_fixed_literal) fixed40x40 pi = 3.14.15; } )"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected token Semicolon"); } BOOST_AUTO_TEST_CASE(invalid_fixed_conversion_leading_zeroes_check) @@ -1228,7 +1358,7 @@ BOOST_AUTO_TEST_CASE(invalid_fixed_conversion_leading_zeroes_check) } } )"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected primary expression"); } BOOST_AUTO_TEST_CASE(payable_accessor) @@ -1238,7 +1368,7 @@ BOOST_AUTO_TEST_CASE(payable_accessor) uint payable x; } )"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected identifier"); } BOOST_AUTO_TEST_CASE(function_type_in_expression) @@ -1271,7 +1401,7 @@ BOOST_AUTO_TEST_CASE(function_type_as_storage_variable_with_modifiers) function (uint, uint) modifier1() returns (uint) f1; } )"; - BOOST_CHECK(!successParse(text)); + CHECK_PARSE_ERROR(text, "Expected token LBrace"); } BOOST_AUTO_TEST_CASE(function_type_as_storage_variable_with_assignment) diff --git a/test/libsolidity/SolidityScanner.cpp b/test/libsolidity/SolidityScanner.cpp index 31b75f25..eb2f042c 100644 --- a/test/libsolidity/SolidityScanner.cpp +++ b/test/libsolidity/SolidityScanner.cpp @@ -1,18 +1,18 @@ /* - This file is part of cpp-ethereum. + This file is part of solidity. - cpp-ethereum is free software: you can redistribute it and/or modify + 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. - cpp-ethereum is distributed in the hope that it will be useful, + 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. + along with solidity. If not, see <http://www.gnu.org/licenses/>. */ /** * @author Christian <c@ethdev.com> diff --git a/test/libsolidity/SolidityTypes.cpp b/test/libsolidity/SolidityTypes.cpp index 87dda9c2..dc3143c8 100644 --- a/test/libsolidity/SolidityTypes.cpp +++ b/test/libsolidity/SolidityTypes.cpp @@ -1,18 +1,18 @@ /* - This file is part of cpp-ethereum. + This file is part of solidity. - cpp-ethereum is free software: you can redistribute it and/or modify + 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. - cpp-ethereum is distributed in the hope that it will be useful, + 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 cpp-ethereum. If not, see <http://www.gnu.org/licenses/>. + along with solidity. If not, see <http://www.gnu.org/licenses/>. */ /** * @author Christian <c@ethdev.com> |