This commit is contained in:
chriseth 2016-10-19 18:43:42 +02:00
parent ff3553a348
commit 87b148494b
3 changed files with 197 additions and 26 deletions

View File

@ -7669,6 +7669,42 @@ BOOST_AUTO_TEST_CASE(pass_function_types_externally)
BOOST_CHECK(callContractFunction("f2(uint256)", 7) == encodeArgs(u256(8))); BOOST_CHECK(callContractFunction("f2(uint256)", 7) == encodeArgs(u256(8)));
} }
BOOST_AUTO_TEST_CASE(receive_external_function_type)
{
char const* sourceCode = R"(
contract C {
function g() returns (uint) { return 7; }
function f(function() external returns (uint) g) returns (uint) {
return g();
}
}
)";
compileAndRun(sourceCode, 0, "C");
BOOST_CHECK(callContractFunction(
"f(bytes24)",
FixedHash<4>(dev::keccak256("g()")).asBytes() + m_contractAddress.asBytes() + bytes(32 - 4 - 20, 0)
) == encodeArgs(u256(7)));
}
BOOST_AUTO_TEST_CASE(return_external_function_type)
{
char const* sourceCode = R"(
contract C {
function g() {}
function f() returns (function() external) {
return this.g;
}
}
)";
compileAndRun(sourceCode, 0, "C");
BOOST_CHECK(
callContractFunction("f()") ==
FixedHash<4>(dev::keccak256("g()")).asBytes() + m_contractAddress.asBytes() + bytes(32 - 4 - 20, 0)
);
}
BOOST_AUTO_TEST_CASE(store_function) BOOST_AUTO_TEST_CASE(store_function)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(
@ -7676,7 +7712,7 @@ BOOST_AUTO_TEST_CASE(store_function)
function addTwo(uint x) returns (uint) { return x + 2; } function addTwo(uint x) returns (uint) { return x + 2; }
} }
contract C { contract C {
function (function (uint) external returns (uint)) returns (uint) ev = eval; function (function (uint) external returns (uint)) returns (uint) ev;
function (uint) external returns (uint) x; function (uint) external returns (uint) x;
function store(function(uint) external returns (uint) y) { function store(function(uint) external returns (uint) y) {
x = y; x = y;
@ -7685,6 +7721,7 @@ BOOST_AUTO_TEST_CASE(store_function)
return y(7); return y(7);
} }
function t() returns (uint) { function t() returns (uint) {
ev = eval;
this.store((new Other()).addTwo); this.store((new Other()).addTwo);
return ev(x); return ev(x);
} }
@ -7728,15 +7765,15 @@ BOOST_AUTO_TEST_CASE(call_function_returning_function)
function f0() returns (uint) { function f0() returns (uint) {
return 2; return 2;
} }
function f1() returns (function() returns (uint)) { function f1() internal returns (function() returns (uint)) {
returns f0; return f0;
} }
function f2() returns (function() returns (function () returns (uint))) { function f2() internal returns (function() returns (function () returns (uint))) {
returns f1; return f1;
} }
function f3() returns (function() returns (function () returns (function () returns (uint)))) function f3() internal returns (function() returns (function () returns (function () returns (uint))))
{ {
returns f2; return f2;
} }
function f() returns (uint) { function f() returns (uint) {
function() returns(function() returns(function() returns(function() returns(uint)))) x; function() returns(function() returns(function() returns(function() returns(uint)))) x;
@ -7746,20 +7783,17 @@ BOOST_AUTO_TEST_CASE(call_function_returning_function)
} }
)"; )";
compileAndRun(sourceCode, 0, "C"); compileAndRun(sourceCode, 0, "test");
BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(2))); BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(2)));
} }
BOOST_AUTO_TEST_CASE(array_of_functions) BOOST_AUTO_TEST_CASE(mapping_of_functions)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(
contract Flow { contract Flow {
bool success; bool public success;
function checkSuccess() returns(bool) {
return success;
}
mapping (address => function () internal returns()) stages; mapping (address => function () internal) stages;
function stage0() internal { function stage0() internal {
stages[msg.sender] = stage1; stages[msg.sender] = stage1;
@ -7773,24 +7807,140 @@ BOOST_AUTO_TEST_CASE(array_of_functions)
success = true; success = true;
} }
function f () { function Flow() {
if (0 == steps[msg.sender])
stages[msg.sender] = stage0; stages[msg.sender] = stage0;
}
function f() {
stages[msg.sender](); stages[msg.sender]();
} }
} }
)"; )";
compileAndRun(sourceCode, 0, "C"); compileAndRun(sourceCode, 0, "Flow");
BOOST_CHECK(callContractFunction("checkSuccess()") == encodeArgs(false)); BOOST_CHECK(callContractFunction("checkSuccess()") == encodeArgs(false));
callContractFunction("f()"); BOOST_CHECK(callContractFunction("f()") == encodeArgs());
callContractFunction("f()"); BOOST_CHECK(callContractFunction("f()") == encodeArgs());
BOOST_CHECK(callContractFunction("checkSuccess()") == encodeArgs(false)); BOOST_CHECK(callContractFunction("checkSuccess()") == encodeArgs(false));
callContractFunction("f()"); BOOST_CHECK(callContractFunction("f()") == encodeArgs());
BOOST_CHECK(callContractFunction("checkSuccess()") == encodeArgs(true)); BOOST_CHECK(callContractFunction("checkSuccess()") == encodeArgs(true));
} }
// TODO: arrays, libraries with external functions BOOST_AUTO_TEST_CASE(packed_functions)
{
char const* sourceCode = R"(
contract C {
// these should take the same slot
function() returns (uint) a;
function() external returns (uint) b;
uint8 public x;
function set() {
x = 2;
a = g;
b = h;
}
function t1() returns (uint) {
return a();
}
function t2() returns (uint) {
return b();
}
function g() returns (uint) {
return 7;
}
function h() returns (uint) {
return 8;
}
}
)";
compileAndRun(sourceCode, 0, "C");
BOOST_CHECK(callContractFunction("set()") == encodeArgs());
BOOST_CHECK(callContractFunction("t1()") == encodeArgs(u256(7)));
BOOST_CHECK(callContractFunction("t2()") == encodeArgs(u256(8)));
BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(2)));
}
BOOST_AUTO_TEST_CASE(function_memory_array)
{
char const* sourceCode = R"(
contract C {
function a(uint x) returns (uint) { return x + 1; }
function b(uint x) returns (uint) { return x + 2; }
function c(uint x) returns (uint) { return x + 3; }
function d(uint x) returns (uint) { return x + 5; }
function e(uint x) returns (uint) { return x + 8; }
function test(uint x, uint i) returns (uint) {
function(uint) internal returns (uint)[] arr =
new function(uint) internal returns (uint)[](10);
arr[0] = a;
arr[1] = b;
arr[2] = c;
arr[3] = d;
arr[4] = e;
return arr[i](x);
}
}
)";
compileAndRun(sourceCode, 0, "C");
BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(0)) == encodeArgs(u256(11)));
BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(1)) == encodeArgs(u256(12)));
BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(2)) == encodeArgs(u256(13)));
BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(3)) == encodeArgs(u256(15)));
BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(4)) == encodeArgs(u256(18)));
BOOST_CHECK(callContractFunction("test(uint256,uint256)", u256(10), u256(5)) == encodeArgs());
}
BOOST_AUTO_TEST_CASE(function_delete)
{
char const* sourceCode = R"(
contract C {
function a() returns (uint) { return 7; }
function() internal returns (uint) y;
function set() returns (uint) {
y = a;
return y();
}
funciton d() returns (uint) {
delete y;
return 1;
}
function ca() returns (uint) {
return y();
}
}
)";
compileAndRun(sourceCode, 0, "C");
BOOST_CHECK(callContractFunction("set()") == encodeArgs(u256(7)));
BOOST_CHECK(callContractFunction("ca()") == encodeArgs(u256(7)));
BOOST_CHECK(callContractFunction("d()") == encodeArgs(u256(1)));
BOOST_CHECK(callContractFunction("ca()") == encodeArgs());
}
BOOST_AUTO_TEST_CASE(copy_function_storage_array)
{
char const* sourceCode = R"(
contract C {
function() internal returns (uint)[] x;
function() internal returns (uint)[] y;
function test() returns (uint) {
x.length = 10;
x[9] = a;
y = x;
return y[9]();
}
function a() returns (uint) {
return 7;
}
}
)";
compileAndRun(sourceCode, 0, "C");
BOOST_CHECK(callContractFunction("test()") == encodeArgs(u256(7)));
}
BOOST_AUTO_TEST_CASE(shift_constant_left) BOOST_AUTO_TEST_CASE(shift_constant_left)
{ {

View File

@ -4227,6 +4227,7 @@ BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter_in_library_internal
)"; )";
BOOST_CHECK(success(text)); BOOST_CHECK(success(text));
} }
BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter_in_library_external) BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter_in_library_external)
{ {
char const* text = R"( char const* text = R"(
@ -4238,6 +4239,23 @@ BOOST_AUTO_TEST_CASE(internal_function_as_external_parameter_in_library_external
BOOST_CHECK(expectError(text) == Error::Type::TypeError); BOOST_CHECK(expectError(text) == Error::Type::TypeError);
} }
BOOST_AUTO_TEST_CASE(function_type_arrays)
{
char const* text = R"(
contract C {
function(uint) external returns (uint)[] public x;
function(uint) internal returns (uint)[10] y;
function f() {
function(uint) returns (uint)[10] memory a;
function(uint) returns (uint)[10] storage b = y;
function(uint) external returns (uint)[] memory c;
c = new function(uint) external returns (uint)[](200);
}
}
)";
BOOST_CHECK(success(text));
}
BOOST_AUTO_TEST_CASE(invalid_fixed_point_literal) BOOST_AUTO_TEST_CASE(invalid_fixed_point_literal)
{ {
char const* text = R"( char const* text = R"(

View File

@ -1325,11 +1325,14 @@ BOOST_AUTO_TEST_CASE(calling_function)
BOOST_CHECK(successParse(text)); BOOST_CHECK(successParse(text));
} }
BOOST_AUTO_TEST_CASE(array_of_functions) BOOST_AUTO_TEST_CASE(mapping_and_array_of_functions)
{ {
char const* text = R"( char const* text = R"(
contract test { contract test {
mapping (address => function() internal returns ()) stages; mapping (address => function() internal returns (uint)) a;
mapping (address => function() external) b;
mapping (address => function() external[]) c;
function() external[] d;
} }
)"; )";
BOOST_CHECK(successParse(text)); BOOST_CHECK(successParse(text));