2014-10-13 13:07:21 +00:00
|
|
|
/*
|
2016-11-18 23:13:20 +00:00
|
|
|
This file is part of solidity.
|
2014-10-13 13:07:21 +00:00
|
|
|
|
2016-11-18 23:13:20 +00:00
|
|
|
solidity is free software: you can redistribute it and/or modify
|
2014-10-13 13:07:21 +00:00
|
|
|
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.
|
|
|
|
|
2016-11-18 23:13:20 +00:00
|
|
|
solidity is distributed in the hope that it will be useful,
|
2014-10-13 13:07:21 +00:00
|
|
|
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
|
2016-11-18 23:13:20 +00:00
|
|
|
along with solidity. If not, see <http://www.gnu.org/licenses/>.
|
2014-10-13 13:07:21 +00:00
|
|
|
*/
|
|
|
|
/**
|
|
|
|
* @author Christian <c@ethdev.com>
|
|
|
|
* @date 2014
|
|
|
|
* Unit tests for the name and type resolution of the solidity parser.
|
|
|
|
*/
|
|
|
|
|
2017-08-28 18:40:38 +00:00
|
|
|
#include <test/libsolidity/AnalysisFramework.h>
|
2017-03-03 11:51:51 +00:00
|
|
|
|
2018-03-14 11:04:04 +00:00
|
|
|
#include <test/Options.h>
|
2018-02-23 18:29:20 +00:00
|
|
|
|
2017-08-28 18:40:38 +00:00
|
|
|
#include <libsolidity/ast/AST.h>
|
2017-03-03 11:51:51 +00:00
|
|
|
|
|
|
|
#include <libdevcore/SHA3.h>
|
|
|
|
|
2017-08-28 18:40:38 +00:00
|
|
|
#include <boost/test/unit_test.hpp>
|
|
|
|
|
2017-03-03 11:51:51 +00:00
|
|
|
#include <string>
|
2014-10-13 13:07:21 +00:00
|
|
|
|
2015-01-23 15:37:06 +00:00
|
|
|
using namespace std;
|
|
|
|
|
2014-10-16 12:08:54 +00:00
|
|
|
namespace dev
|
|
|
|
{
|
|
|
|
namespace solidity
|
|
|
|
{
|
|
|
|
namespace test
|
|
|
|
{
|
2014-10-13 13:07:21 +00:00
|
|
|
|
2017-08-28 18:40:38 +00:00
|
|
|
BOOST_FIXTURE_TEST_SUITE(SolidityNameAndTypeResolution, AnalysisFramework)
|
2014-10-13 13:07:21 +00:00
|
|
|
|
2015-03-20 16:50:26 +00:00
|
|
|
BOOST_AUTO_TEST_CASE(function_no_implementation)
|
|
|
|
{
|
2017-08-28 18:40:38 +00:00
|
|
|
SourceUnit const* sourceUnit = nullptr;
|
2016-12-03 20:52:51 +00:00
|
|
|
char const* text = R"(
|
|
|
|
contract test {
|
2017-09-05 15:11:53 +00:00
|
|
|
function functionName(bytes32 input) public returns (bytes32 out);
|
2016-12-03 20:52:51 +00:00
|
|
|
}
|
|
|
|
)";
|
2017-08-28 18:40:38 +00:00
|
|
|
sourceUnit = parseAndAnalyse(text);
|
2015-08-31 16:44:29 +00:00
|
|
|
std::vector<ASTPointer<ASTNode>> nodes = sourceUnit->nodes();
|
2016-08-19 17:57:21 +00:00
|
|
|
ContractDefinition* contract = dynamic_cast<ContractDefinition*>(nodes[1].get());
|
|
|
|
BOOST_REQUIRE(contract);
|
2017-08-02 10:58:22 +00:00
|
|
|
BOOST_CHECK(!contract->annotation().unimplementedFunctions.empty());
|
2015-09-16 14:56:30 +00:00
|
|
|
BOOST_CHECK(!contract->definedFunctions()[0]->isImplemented());
|
2015-03-20 16:50:26 +00:00
|
|
|
}
|
|
|
|
|
2015-03-27 14:15:34 +00:00
|
|
|
BOOST_AUTO_TEST_CASE(abstract_contract)
|
|
|
|
{
|
2017-08-28 18:40:38 +00:00
|
|
|
SourceUnit const* sourceUnit = nullptr;
|
2015-03-27 14:15:34 +00:00
|
|
|
char const* text = R"(
|
2018-06-29 14:52:41 +00:00
|
|
|
contract base { function foo() public; }
|
2017-09-05 15:11:53 +00:00
|
|
|
contract derived is base { function foo() public {} }
|
2016-12-03 20:52:51 +00:00
|
|
|
)";
|
2017-08-28 18:40:38 +00:00
|
|
|
sourceUnit = parseAndAnalyse(text);
|
2015-08-31 16:44:29 +00:00
|
|
|
std::vector<ASTPointer<ASTNode>> nodes = sourceUnit->nodes();
|
2016-08-19 17:57:21 +00:00
|
|
|
ContractDefinition* base = dynamic_cast<ContractDefinition*>(nodes[1].get());
|
|
|
|
ContractDefinition* derived = dynamic_cast<ContractDefinition*>(nodes[2].get());
|
|
|
|
BOOST_REQUIRE(base);
|
2017-08-02 10:58:22 +00:00
|
|
|
BOOST_CHECK(!base->annotation().unimplementedFunctions.empty());
|
2015-09-16 14:56:30 +00:00
|
|
|
BOOST_CHECK(!base->definedFunctions()[0]->isImplemented());
|
2016-08-19 17:57:21 +00:00
|
|
|
BOOST_REQUIRE(derived);
|
2017-08-02 10:58:22 +00:00
|
|
|
BOOST_CHECK(derived->annotation().unimplementedFunctions.empty());
|
2015-09-16 14:56:30 +00:00
|
|
|
BOOST_CHECK(derived->definedFunctions()[0]->isImplemented());
|
2015-03-27 14:15:34 +00:00
|
|
|
}
|
|
|
|
|
2015-06-23 14:56:59 +00:00
|
|
|
BOOST_AUTO_TEST_CASE(abstract_contract_with_overload)
|
|
|
|
{
|
2017-08-28 18:40:38 +00:00
|
|
|
SourceUnit const* sourceUnit = nullptr;
|
2015-06-23 14:56:59 +00:00
|
|
|
char const* text = R"(
|
2018-06-29 14:52:41 +00:00
|
|
|
contract base { function foo(bool) public; }
|
2017-09-05 15:11:53 +00:00
|
|
|
contract derived is base { function foo(uint) public {} }
|
2016-12-03 20:52:51 +00:00
|
|
|
)";
|
2017-08-28 18:40:38 +00:00
|
|
|
sourceUnit = parseAndAnalyse(text);
|
2015-08-31 16:44:29 +00:00
|
|
|
std::vector<ASTPointer<ASTNode>> nodes = sourceUnit->nodes();
|
2016-08-19 17:57:21 +00:00
|
|
|
ContractDefinition* base = dynamic_cast<ContractDefinition*>(nodes[1].get());
|
|
|
|
ContractDefinition* derived = dynamic_cast<ContractDefinition*>(nodes[2].get());
|
2015-06-23 14:56:59 +00:00
|
|
|
BOOST_REQUIRE(base);
|
2017-08-02 10:58:22 +00:00
|
|
|
BOOST_CHECK(!base->annotation().unimplementedFunctions.empty());
|
2015-06-23 14:56:59 +00:00
|
|
|
BOOST_REQUIRE(derived);
|
2017-08-02 10:58:22 +00:00
|
|
|
BOOST_CHECK(!derived->annotation().unimplementedFunctions.empty());
|
2015-06-23 14:56:59 +00:00
|
|
|
}
|
|
|
|
|
2016-06-06 17:35:55 +00:00
|
|
|
BOOST_AUTO_TEST_CASE(implement_abstract_via_constructor)
|
|
|
|
{
|
2017-08-28 18:40:38 +00:00
|
|
|
SourceUnit const* sourceUnit = nullptr;
|
2016-06-06 17:35:55 +00:00
|
|
|
char const* text = R"(
|
2018-06-29 14:52:41 +00:00
|
|
|
contract base { function foo() public; }
|
2018-06-27 11:22:33 +00:00
|
|
|
contract foo is base { constructor() public {} }
|
2016-06-06 17:35:55 +00:00
|
|
|
)";
|
2017-08-28 18:40:38 +00:00
|
|
|
sourceUnit = parseAndAnalyse(text);
|
2016-06-06 17:35:55 +00:00
|
|
|
std::vector<ASTPointer<ASTNode>> nodes = sourceUnit->nodes();
|
2016-08-19 17:57:21 +00:00
|
|
|
BOOST_CHECK_EQUAL(nodes.size(), 3);
|
|
|
|
ContractDefinition* derived = dynamic_cast<ContractDefinition*>(nodes[2].get());
|
|
|
|
BOOST_REQUIRE(derived);
|
2017-08-02 10:58:22 +00:00
|
|
|
BOOST_CHECK(!derived->annotation().unimplementedFunctions.empty());
|
2016-06-06 17:35:55 +00:00
|
|
|
}
|
|
|
|
|
2015-01-07 01:07:34 +00:00
|
|
|
BOOST_AUTO_TEST_CASE(function_canonical_signature)
|
|
|
|
{
|
2017-08-28 18:40:38 +00:00
|
|
|
SourceUnit const* sourceUnit = nullptr;
|
2016-12-03 20:52:51 +00:00
|
|
|
char const* text = R"(
|
|
|
|
contract Test {
|
2017-09-05 15:11:53 +00:00
|
|
|
function foo(uint256 arg1, uint64 arg2, bool arg3) public returns (uint256 ret) {
|
2016-12-03 20:52:51 +00:00
|
|
|
ret = arg1 + arg2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)";
|
2017-08-28 18:40:38 +00:00
|
|
|
sourceUnit = parseAndAnalyse(text);
|
2015-08-31 16:44:29 +00:00
|
|
|
for (ASTPointer<ASTNode> const& node: sourceUnit->nodes())
|
2015-01-07 01:07:34 +00:00
|
|
|
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
|
|
|
|
{
|
2015-08-31 16:44:29 +00:00
|
|
|
auto functions = contract->definedFunctions();
|
2015-03-24 10:11:27 +00:00
|
|
|
BOOST_CHECK_EQUAL("foo(uint256,uint64,bool)", functions[0]->externalSignature());
|
2015-01-07 09:45:59 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
BOOST_AUTO_TEST_CASE(function_canonical_signature_type_aliases)
|
|
|
|
{
|
2017-08-28 18:40:38 +00:00
|
|
|
SourceUnit const* sourceUnit = nullptr;
|
2016-12-03 20:52:51 +00:00
|
|
|
char const* text = R"(
|
|
|
|
contract Test {
|
2017-09-05 15:11:53 +00:00
|
|
|
function boo(uint, bytes32, address) public returns (uint ret) {
|
2016-12-03 20:52:51 +00:00
|
|
|
ret = 5;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
)";
|
2017-08-28 18:40:38 +00:00
|
|
|
sourceUnit = parseAndAnalyse(text);
|
2015-08-31 16:44:29 +00:00
|
|
|
for (ASTPointer<ASTNode> const& node: sourceUnit->nodes())
|
2015-01-07 09:45:59 +00:00
|
|
|
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
|
|
|
|
{
|
2015-08-31 16:44:29 +00:00
|
|
|
auto functions = contract->definedFunctions();
|
2015-03-25 12:58:15 +00:00
|
|
|
if (functions.empty())
|
|
|
|
continue;
|
2015-03-24 10:11:27 +00:00
|
|
|
BOOST_CHECK_EQUAL("boo(uint256,bytes32,address)", functions[0]->externalSignature());
|
2015-01-07 01:07:34 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-03-23 17:08:45 +00:00
|
|
|
BOOST_AUTO_TEST_CASE(function_external_types)
|
|
|
|
{
|
2017-08-28 18:40:38 +00:00
|
|
|
SourceUnit const* sourceUnit = nullptr;
|
2015-03-23 17:08:45 +00:00
|
|
|
char const* text = R"(
|
2015-03-25 12:58:15 +00:00
|
|
|
contract C {
|
|
|
|
uint a;
|
|
|
|
}
|
2015-03-23 17:08:45 +00:00
|
|
|
contract Test {
|
2017-04-14 14:48:59 +00:00
|
|
|
function boo(uint, bool, bytes8, bool[2], uint[], C, address[]) external returns (uint ret) {
|
2016-12-03 20:52:51 +00:00
|
|
|
ret = 5;
|
2015-03-23 17:08:45 +00:00
|
|
|
}
|
2016-12-03 20:52:51 +00:00
|
|
|
}
|
|
|
|
)";
|
2017-08-28 18:40:38 +00:00
|
|
|
sourceUnit = parseAndAnalyse(text);
|
2015-08-31 16:44:29 +00:00
|
|
|
for (ASTPointer<ASTNode> const& node: sourceUnit->nodes())
|
2015-03-23 17:08:45 +00:00
|
|
|
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
|
|
|
|
{
|
2015-08-31 16:44:29 +00:00
|
|
|
auto functions = contract->definedFunctions();
|
2015-03-25 12:58:15 +00:00
|
|
|
if (functions.empty())
|
|
|
|
continue;
|
2015-03-30 12:34:38 +00:00
|
|
|
BOOST_CHECK_EQUAL("boo(uint256,bool,bytes8,bool[2],uint256[],address,address[])", functions[0]->externalSignature());
|
2015-03-23 17:08:45 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-11 11:47:21 +00:00
|
|
|
BOOST_AUTO_TEST_CASE(enum_external_type)
|
|
|
|
{
|
2017-08-28 18:40:38 +00:00
|
|
|
SourceUnit const* sourceUnit = nullptr;
|
2015-05-11 11:47:21 +00:00
|
|
|
char const* text = R"(
|
2018-05-23 09:34:01 +00:00
|
|
|
// test for bug #1801
|
2015-05-11 11:47:21 +00:00
|
|
|
contract Test {
|
|
|
|
enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
|
|
|
|
function boo(ActionChoices enumArg) external returns (uint ret) {
|
2015-05-11 14:24:04 +00:00
|
|
|
ret = 5;
|
2015-05-11 11:47:21 +00:00
|
|
|
}
|
2016-12-03 20:52:51 +00:00
|
|
|
}
|
|
|
|
)";
|
2017-08-28 18:40:38 +00:00
|
|
|
sourceUnit = parseAndAnalyse(text);
|
2015-08-31 16:44:29 +00:00
|
|
|
for (ASTPointer<ASTNode> const& node: sourceUnit->nodes())
|
2015-05-11 11:47:21 +00:00
|
|
|
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
|
|
|
|
{
|
2015-08-31 16:44:29 +00:00
|
|
|
auto functions = contract->definedFunctions();
|
2015-05-11 11:47:21 +00:00
|
|
|
if (functions.empty())
|
|
|
|
continue;
|
|
|
|
BOOST_CHECK_EQUAL("boo(uint8)", functions[0]->externalSignature());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-08 09:14:58 +00:00
|
|
|
BOOST_AUTO_TEST_CASE(external_structs)
|
|
|
|
{
|
2017-06-09 16:28:13 +00:00
|
|
|
char const* text = R"(
|
2017-12-11 02:39:39 +00:00
|
|
|
pragma experimental ABIEncoderV2;
|
2017-06-09 16:28:13 +00:00
|
|
|
contract Test {
|
|
|
|
enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
|
2018-06-06 09:15:22 +00:00
|
|
|
struct Simple { uint i; }
|
2017-09-14 15:03:59 +00:00
|
|
|
struct Nested { X[2][] a; uint y; }
|
2018-06-06 09:15:22 +00:00
|
|
|
struct X { bytes32 x; Test t; Simple[] s; }
|
|
|
|
function f(ActionChoices, uint, Simple) external {}
|
2017-06-13 08:51:49 +00:00
|
|
|
function g(Test, Nested) external {}
|
2018-07-11 11:23:33 +00:00
|
|
|
function h(function(Nested memory) external returns (uint)[]) external {}
|
2017-06-09 16:28:13 +00:00
|
|
|
function i(Nested[]) external {}
|
|
|
|
}
|
|
|
|
)";
|
2017-09-01 11:37:40 +00:00
|
|
|
SourceUnit const* sourceUnit = parseAndAnalyse(text);
|
2017-06-09 16:28:13 +00:00
|
|
|
for (ASTPointer<ASTNode> const& node: sourceUnit->nodes())
|
|
|
|
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
|
|
|
|
{
|
|
|
|
auto functions = contract->definedFunctions();
|
|
|
|
BOOST_REQUIRE(!functions.empty());
|
2018-06-06 09:15:22 +00:00
|
|
|
BOOST_CHECK_EQUAL("f(uint8,uint256,(uint256))", functions[0]->externalSignature());
|
|
|
|
BOOST_CHECK_EQUAL("g(address,((bytes32,address,(uint256)[])[2][],uint256))", functions[1]->externalSignature());
|
2017-06-09 16:28:13 +00:00
|
|
|
BOOST_CHECK_EQUAL("h(function[])", functions[2]->externalSignature());
|
2018-06-06 09:15:22 +00:00
|
|
|
BOOST_CHECK_EQUAL("i(((bytes32,address,(uint256)[])[2][],uint256)[])", functions[3]->externalSignature());
|
2017-06-09 16:28:13 +00:00
|
|
|
}
|
2017-06-08 09:14:58 +00:00
|
|
|
}
|
|
|
|
|
2017-09-01 11:37:40 +00:00
|
|
|
BOOST_AUTO_TEST_CASE(external_structs_in_libraries)
|
|
|
|
{
|
|
|
|
char const* text = R"(
|
2017-12-11 02:39:39 +00:00
|
|
|
pragma experimental ABIEncoderV2;
|
2017-09-01 11:37:40 +00:00
|
|
|
library Test {
|
|
|
|
enum ActionChoices { GoLeft, GoRight, GoStraight, Sit }
|
2018-06-06 09:15:22 +00:00
|
|
|
struct Simple { uint i; }
|
2017-09-14 15:03:59 +00:00
|
|
|
struct Nested { X[2][] a; uint y; }
|
2018-06-06 09:15:22 +00:00
|
|
|
struct X { bytes32 x; Test t; Simple[] s; }
|
|
|
|
function f(ActionChoices, uint, Simple) external {}
|
2017-09-01 11:37:40 +00:00
|
|
|
function g(Test, Nested) external {}
|
2018-07-11 11:23:33 +00:00
|
|
|
function h(function(Nested memory) external returns (uint)[]) external {}
|
2017-09-01 11:37:40 +00:00
|
|
|
function i(Nested[]) external {}
|
|
|
|
}
|
|
|
|
)";
|
|
|
|
SourceUnit const* sourceUnit = parseAndAnalyse(text);
|
|
|
|
for (ASTPointer<ASTNode> const& node: sourceUnit->nodes())
|
|
|
|
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
|
|
|
|
{
|
|
|
|
auto functions = contract->definedFunctions();
|
|
|
|
BOOST_REQUIRE(!functions.empty());
|
2018-06-06 09:15:22 +00:00
|
|
|
BOOST_CHECK_EQUAL("f(Test.ActionChoices,uint256,Test.Simple)", functions[0]->externalSignature());
|
2017-09-01 11:37:40 +00:00
|
|
|
BOOST_CHECK_EQUAL("g(Test,Test.Nested)", functions[1]->externalSignature());
|
|
|
|
BOOST_CHECK_EQUAL("h(function[])", functions[2]->externalSignature());
|
|
|
|
BOOST_CHECK_EQUAL("i(Test.Nested[])", functions[3]->externalSignature());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-09-14 15:03:59 +00:00
|
|
|
BOOST_AUTO_TEST_CASE(struct_with_mapping_in_library)
|
|
|
|
{
|
|
|
|
char const* text = R"(
|
|
|
|
library Test {
|
|
|
|
struct Nested { mapping(uint => uint)[2][] a; uint y; }
|
|
|
|
struct X { Nested n; }
|
|
|
|
function f(X storage x) external {}
|
|
|
|
}
|
|
|
|
)";
|
|
|
|
SourceUnit const* sourceUnit = parseAndAnalyse(text);
|
|
|
|
for (ASTPointer<ASTNode> const& node: sourceUnit->nodes())
|
|
|
|
if (ContractDefinition* contract = dynamic_cast<ContractDefinition*>(node.get()))
|
|
|
|
{
|
|
|
|
auto functions = contract->definedFunctions();
|
|
|
|
BOOST_REQUIRE(!functions.empty());
|
|
|
|
BOOST_CHECK_EQUAL("f(Test.X storage)", functions[0]->externalSignature());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-05-30 19:04:34 +00:00
|
|
|
BOOST_AUTO_TEST_CASE(state_variable_accessors)
|
2017-09-14 15:03:59 +00:00
|
|
|
{
|
|
|
|
char const* text = R"(
|
2018-05-30 19:04:34 +00:00
|
|
|
contract test {
|
|
|
|
function fun() public {
|
|
|
|
uint64(2);
|
|
|
|
}
|
|
|
|
uint256 public foo;
|
|
|
|
mapping(uint=>bytes4) public map;
|
|
|
|
mapping(uint=>mapping(uint=>bytes4)) public multiple_map;
|
2017-09-14 15:03:59 +00:00
|
|
|
}
|
|
|
|
)";
|
|
|
|
|
2018-05-30 19:04:34 +00:00
|
|
|
SourceUnit const* source;
|
|
|
|
ContractDefinition const* contract;
|
|
|
|
source = parseAndAnalyse(text);
|
|
|
|
BOOST_REQUIRE((contract = retrieveContractByName(*source, "test")) != nullptr);
|
|
|
|
FunctionTypePointer function = retrieveFunctionBySignature(*contract, "foo()");
|
|
|
|
BOOST_REQUIRE(function && function->hasDeclaration());
|
|
|
|
auto returnParams = function->returnParameterTypes();
|
|
|
|
BOOST_CHECK_EQUAL(returnParams.at(0)->canonicalName(), "uint256");
|
|
|
|
BOOST_CHECK(function->stateMutability() == StateMutability::View);
|
2017-09-14 15:03:59 +00:00
|
|
|
|
2018-05-30 19:04:34 +00:00
|
|
|
function = retrieveFunctionBySignature(*contract, "map(uint256)");
|
|
|
|
BOOST_REQUIRE(function && function->hasDeclaration());
|
|
|
|
auto params = function->parameterTypes();
|
|
|
|
BOOST_CHECK_EQUAL(params.at(0)->canonicalName(), "uint256");
|
|
|
|
returnParams = function->returnParameterTypes();
|
|
|
|
BOOST_CHECK_EQUAL(returnParams.at(0)->canonicalName(), "bytes4");
|
|
|
|
BOOST_CHECK(function->stateMutability() == StateMutability::View);
|
|
|
|
|
|
|
|
function = retrieveFunctionBySignature(*contract, "multiple_map(uint256,uint256)");
|
|
|
|
BOOST_REQUIRE(function && function->hasDeclaration());
|
|
|
|
params = function->parameterTypes();
|
|
|
|
BOOST_CHECK_EQUAL(params.at(0)->canonicalName(), "uint256");
|
|
|
|
BOOST_CHECK_EQUAL(params.at(1)->canonicalName(), "uint256");
|
|
|
|
returnParams = function->returnParameterTypes();
|
|
|
|
BOOST_CHECK_EQUAL(returnParams.at(0)->canonicalName(), "bytes4");
|
|
|
|
BOOST_CHECK(function->stateMutability() == StateMutability::View);
|
2017-09-14 15:03:59 +00:00
|
|
|
}
|
|
|
|
|
2018-05-30 19:04:34 +00:00
|
|
|
BOOST_AUTO_TEST_CASE(private_state_variable)
|
2017-09-14 15:03:59 +00:00
|
|
|
{
|
|
|
|
char const* text = R"(
|
2018-05-30 19:04:34 +00:00
|
|
|
contract test {
|
|
|
|
function fun() public {
|
|
|
|
uint64(2);
|
2017-09-27 13:11:44 +00:00
|
|
|
}
|
2018-05-30 19:04:34 +00:00
|
|
|
uint256 private foo;
|
|
|
|
uint256 internal bar;
|
2017-09-27 13:11:44 +00:00
|
|
|
}
|
|
|
|
)";
|
|
|
|
|
2018-05-30 19:04:34 +00:00
|
|
|
ContractDefinition const* contract;
|
|
|
|
SourceUnit const* source = parseAndAnalyse(text);
|
|
|
|
BOOST_CHECK((contract = retrieveContractByName(*source, "test")) != nullptr);
|
|
|
|
FunctionTypePointer function;
|
|
|
|
function = retrieveFunctionBySignature(*contract, "foo()");
|
|
|
|
BOOST_CHECK_MESSAGE(function == nullptr, "Accessor function of a private variable should not exist");
|
|
|
|
function = retrieveFunctionBySignature(*contract, "bar()");
|
|
|
|
BOOST_CHECK_MESSAGE(function == nullptr, "Accessor function of an internal variable should not exist");
|
2017-09-20 13:54:41 +00:00
|
|
|
}
|
|
|
|
|
2018-05-30 19:04:34 +00:00
|
|
|
BOOST_AUTO_TEST_CASE(string)
|
2018-02-16 15:55:21 +00:00
|
|
|
{
|
2018-05-30 19:04:34 +00:00
|
|
|
char const* sourceCode = R"(
|
2018-02-16 15:55:21 +00:00
|
|
|
contract C {
|
2018-05-30 19:04:34 +00:00
|
|
|
string s;
|
|
|
|
function f(string x) external { s = x; }
|
2018-02-16 15:55:21 +00:00
|
|
|
}
|
|
|
|
)";
|
2018-05-30 19:04:34 +00:00
|
|
|
BOOST_CHECK_NO_THROW(parseAndAnalyse(sourceCode));
|
2018-05-23 09:36:39 +00:00
|
|
|
}
|
|
|
|
|
2018-05-30 19:04:34 +00:00
|
|
|
BOOST_AUTO_TEST_CASE(dynamic_return_types_not_possible)
|
2018-05-23 09:36:39 +00:00
|
|
|
{
|
2018-05-30 19:04:34 +00:00
|
|
|
char const* sourceCode = R"(
|
2018-02-16 15:55:21 +00:00
|
|
|
contract C {
|
2018-07-12 04:18:50 +00:00
|
|
|
function f(uint) public returns (string memory);
|
2018-05-30 19:04:34 +00:00
|
|
|
function g() public {
|
2018-06-28 13:19:53 +00:00
|
|
|
string memory x = this.f(2);
|
2018-05-30 19:04:34 +00:00
|
|
|
// we can assign to x but it is not usable.
|
|
|
|
bytes(x).length;
|
2018-02-16 15:55:21 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
)";
|
2018-05-30 19:04:34 +00:00
|
|
|
if (dev::test::Options::get().evmVersion() == EVMVersion::homestead())
|
2018-06-28 13:19:53 +00:00
|
|
|
CHECK_ERROR(sourceCode, TypeError, "Type inaccessible dynamic type is not implicitly convertible to expected type string memory.");
|
2018-05-30 19:04:34 +00:00
|
|
|
else
|
2018-06-28 13:19:53 +00:00
|
|
|
CHECK_SUCCESS_NO_WARNINGS(sourceCode);
|
2018-05-23 09:36:39 +00:00
|
|
|
}
|
|
|
|
|
2018-05-30 19:04:34 +00:00
|
|
|
BOOST_AUTO_TEST_CASE(warn_nonpresent_pragma)
|
2018-05-23 09:36:39 +00:00
|
|
|
{
|
|
|
|
char const* text = R"(
|
2018-05-30 19:04:34 +00:00
|
|
|
contract C {}
|
2018-02-16 15:55:21 +00:00
|
|
|
)";
|
2018-05-30 19:04:34 +00:00
|
|
|
auto sourceAndError = parseAnalyseAndReturnError(text, true, false);
|
|
|
|
BOOST_REQUIRE(!sourceAndError.second.empty());
|
|
|
|
BOOST_REQUIRE(!!sourceAndError.first);
|
|
|
|
BOOST_CHECK(searchErrorMessage(*sourceAndError.second.front(), "Source file does not specify required compiler version!"));
|
2018-02-16 15:55:21 +00:00
|
|
|
}
|
|
|
|
|
2018-05-30 19:04:34 +00:00
|
|
|
BOOST_AUTO_TEST_CASE(unsatisfied_version)
|
2018-02-16 16:32:54 +00:00
|
|
|
{
|
|
|
|
char const* text = R"(
|
2018-05-30 19:04:34 +00:00
|
|
|
pragma solidity ^99.99.0;
|
2018-02-16 16:32:54 +00:00
|
|
|
)";
|
2018-05-30 19:04:34 +00:00
|
|
|
auto sourceAndError = parseAnalyseAndReturnError(text, false, false, false);
|
|
|
|
BOOST_REQUIRE(!sourceAndError.second.empty());
|
|
|
|
BOOST_REQUIRE(!!sourceAndError.first);
|
|
|
|
BOOST_CHECK(sourceAndError.second.front()->type() == Error::Type::SyntaxError);
|
|
|
|
BOOST_CHECK(searchErrorMessage(*sourceAndError.second.front(), "Source file requires different compiler version"));
|
2018-05-23 09:36:39 +00:00
|
|
|
}
|
|
|
|
|
2018-05-30 19:04:34 +00:00
|
|
|
BOOST_AUTO_TEST_CASE(returndatasize_as_variable)
|
2018-05-23 09:36:39 +00:00
|
|
|
{
|
|
|
|
char const* text = R"(
|
2018-05-30 19:04:34 +00:00
|
|
|
contract c { function f() public { uint returndatasize; assembly { returndatasize }}}
|
2018-02-16 16:32:54 +00:00
|
|
|
)";
|
2018-05-30 19:04:34 +00:00
|
|
|
vector<pair<Error::Type, std::string>> expectations(vector<pair<Error::Type, std::string>>{
|
|
|
|
{Error::Type::Warning, "Variable is shadowed in inline assembly by an instruction of the same name"},
|
|
|
|
{Error::Type::Warning, "The use of non-functional instructions is deprecated."},
|
|
|
|
{Error::Type::DeclarationError, "Unbalanced stack"}
|
|
|
|
});
|
|
|
|
if (!dev::test::Options::get().evmVersion().supportsReturndata())
|
|
|
|
expectations.emplace_back(make_pair(Error::Type::Warning, std::string("\"returndatasize\" instruction is only available for Byzantium-compatible")));
|
|
|
|
CHECK_ALLOW_MULTI(text, expectations);
|
2018-02-16 16:32:54 +00:00
|
|
|
}
|
|
|
|
|
2018-06-04 17:14:25 +00:00
|
|
|
BOOST_AUTO_TEST_CASE(create2_as_variable)
|
|
|
|
{
|
|
|
|
char const* text = R"(
|
|
|
|
contract c { function f() public { uint create2; assembly { create2(0, 0, 0, 0) } }}
|
|
|
|
)";
|
|
|
|
// This needs special treatment, because the message mentions the EVM version,
|
|
|
|
// so cannot be run via isoltest.
|
|
|
|
CHECK_ALLOW_MULTI(text, (std::vector<std::pair<Error::Type, std::string>>{
|
|
|
|
{Error::Type::Warning, "Variable is shadowed in inline assembly by an instruction of the same name"},
|
|
|
|
{Error::Type::Warning, "The \"create2\" instruction is not supported by the VM version"},
|
|
|
|
{Error::Type::DeclarationError, "Unbalanced stack"},
|
|
|
|
{Error::Type::Warning, "not supposed to return values"}
|
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
2018-02-26 10:13:21 +00:00
|
|
|
BOOST_AUTO_TEST_CASE(getter_is_memory_type)
|
|
|
|
{
|
|
|
|
char const* text = R"(
|
|
|
|
contract C {
|
|
|
|
struct S { string m; }
|
|
|
|
string[] public x;
|
|
|
|
S[] public y;
|
|
|
|
}
|
|
|
|
)";
|
|
|
|
CHECK_SUCCESS_NO_WARNINGS(text);
|
|
|
|
// Check that the getters return a memory strings, not a storage strings.
|
|
|
|
ContractDefinition const& c = dynamic_cast<ContractDefinition const&>(*m_compiler.ast("").nodes().at(1));
|
|
|
|
BOOST_CHECK(c.interfaceFunctions().size() == 2);
|
|
|
|
for (auto const& f: c.interfaceFunctions())
|
|
|
|
{
|
|
|
|
auto const& retType = f.second->returnParameterTypes().at(0);
|
|
|
|
BOOST_CHECK(retType->dataStoredIn(DataLocation::Memory));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-10-13 13:07:21 +00:00
|
|
|
BOOST_AUTO_TEST_SUITE_END()
|
|
|
|
|
2014-10-16 12:08:54 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
} // end namespaces
|