diff options
Diffstat (limited to 'test/libsolidity/SolidityEndToEndTest.cpp')
-rw-r--r-- | test/libsolidity/SolidityEndToEndTest.cpp | 389 |
1 files changed, 379 insertions, 10 deletions
diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 3cd3b9b7..bee83007 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -523,6 +523,96 @@ BOOST_AUTO_TEST_CASE(do_while_loop_continue) ABI_CHECK(callContractFunction("f()"), encodeArgs(42)); } +BOOST_AUTO_TEST_CASE(array_multiple_local_vars) +{ + char const* sourceCode = R"( + contract test { + function f(uint256[] seq) external pure returns (uint256) { + uint i = 0; + uint sum = 0; + while (i < seq.length) + { + uint idx = i; + if (idx >= 10) break; + uint x = seq[idx]; + if (x >= 1000) { + uint n = i + 1; + i = n; + continue; + } + else { + uint y = sum + x; + sum = y; + } + if (sum >= 500) return sum; + i++; + } + return sum; + } + } + )"; + compileAndRun(sourceCode); + + ABI_CHECK(callContractFunction("f(uint256[])", 32, 3, u256(1000), u256(1), u256(2)), encodeArgs(3)); + ABI_CHECK(callContractFunction("f(uint256[])", 32, 3, u256(100), u256(500), u256(300)), encodeArgs(600)); + ABI_CHECK(callContractFunction( + "f(uint256[])", 32, 11, + u256(1), u256(2), u256(3), u256(4), u256(5), u256(6), u256(7), u256(8), u256(9), u256(10), u256(111) + ), encodeArgs(55)); +} + + +BOOST_AUTO_TEST_CASE(do_while_loop_multiple_local_vars) +{ + char const* sourceCode = R"( + contract test { + function f(uint x) public pure returns(uint r) { + uint i = 0; + do + { + uint z = x * 2; + if (z < 4) break; + else { + uint k = z + 1; + if (k < 8) { + x++; + continue; + } + } + if (z > 12) return 0; + x++; + i++; + } while (true); + return 42; + } + } + )"; + compileAndRun(sourceCode); + + auto do_while = [](u256 n) -> u256 + { + u256 i = 0; + do + { + u256 z = n * 2; + if (z < 4) break; + else { + u256 k = z + 1; + if (k < 8) { + n++; + continue; + } + } + if (z > 12) return 0; + n++; + i++; + } while (true); + return 42; + }; + + testContractAgainstCppOnRange("f(uint256)", do_while, 0, 12); +} + BOOST_AUTO_TEST_CASE(nested_loops) { // tests that break and continue statements in nested loops jump to the correct place @@ -574,6 +664,178 @@ BOOST_AUTO_TEST_CASE(nested_loops) testContractAgainstCppOnRange("f(uint256)", nested_loops_cpp, 0, 12); } +BOOST_AUTO_TEST_CASE(nested_loops_multiple_local_vars) +{ + // tests that break and continue statements in nested loops jump to the correct place + // and free local variables properly + char const* sourceCode = R"( + contract test { + function f(uint x) returns(uint y) { + while (x > 0) { + uint z = x + 10; + uint k = z + 1; + if (k > 20) { + break; + uint p = 100; + k += p; + } + if (k > 15) { + x--; + continue; + uint t = 1000; + x += t; + } + while (k > 10) { + uint m = k - 1; + if (m == 10) return x; + return k; + uint h = 10000; + z += h; + } + x--; + break; + } + return x; + } + } + )"; + compileAndRun(sourceCode); + + auto nested_loops_cpp = [](u256 n) -> u256 + { + while (n > 0) + { + u256 z = n + 10; + u256 k = z + 1; + if (k > 20) break; + if (k > 15) { + n--; + continue; + } + while (k > 10) + { + u256 m = k - 1; + if (m == 10) return n; + return k; + } + n--; + break; + } + + return n; + }; + + testContractAgainstCppOnRange("f(uint256)", nested_loops_cpp, 0, 12); +} + +BOOST_AUTO_TEST_CASE(for_loop_multiple_local_vars) +{ + char const* sourceCode = R"( + contract test { + function f(uint x) public pure returns(uint r) { + for (uint i = 0; i < 12; i++) + { + uint z = x + 1; + if (z < 4) break; + else { + uint k = z * 2; + if (i + k < 10) { + x++; + continue; + } + } + if (z > 8) return 0; + x++; + } + return 42; + } + } + )"; + compileAndRun(sourceCode); + + auto for_loop = [](u256 n) -> u256 + { + for (u256 i = 0; i < 12; i++) + { + u256 z = n + 1; + if (z < 4) break; + else { + u256 k = z * 2; + if (i + k < 10) { + n++; + continue; + } + } + if (z > 8) return 0; + n++; + } + return 42; + }; + + testContractAgainstCppOnRange("f(uint256)", for_loop, 0, 12); +} + +BOOST_AUTO_TEST_CASE(nested_for_loop_multiple_local_vars) +{ + char const* sourceCode = R"( + contract test { + function f(uint x) public pure returns(uint r) { + for (uint i = 0; i < 5; i++) + { + uint z = x + 1; + if (z < 3) { + break; + uint p = z + 2; + } + for (uint j = 0; j < 5; j++) + { + uint k = z * 2; + if (j + k < 8) { + x++; + continue; + uint t = z * 3; + } + x++; + if (x > 20) { + return 84; + uint h = x + 42; + } + } + if (x > 30) { + return 42; + uint b = 0xcafe; + } + } + return 42; + } + } + )"; + compileAndRun(sourceCode); + + auto for_loop = [](u256 n) -> u256 + { + for (u256 i = 0; i < 5; i++) + { + u256 z = n + 1; + if (z < 3) break; + for (u256 j = 0; j < 5; j++) + { + u256 k = z * 2; + if (j + k < 8) { + n++; + continue; + } + n++; + if (n > 20) return 84; + } + if (n > 30) return 42; + } + return 42; + }; + + testContractAgainstCppOnRange("f(uint256)", for_loop, 0, 12); +} + BOOST_AUTO_TEST_CASE(for_loop) { char const* sourceCode = R"( @@ -1273,7 +1535,7 @@ BOOST_AUTO_TEST_CASE(struct_reference) function set() public { data.z = 2; mapping(uint8 => s2) map = data.recursive; - s2 inner = map[0]; + s2 storage inner = map[0]; inner.z = 3; inner.recursive[0].z = inner.recursive[1].z + 1; } @@ -6112,7 +6374,7 @@ BOOST_AUTO_TEST_CASE(struct_assign_reference_to_struct) } function assign() public returns (uint ret_local, uint ret_global, uint ret_global3, uint ret_global1) { - testStruct x = data1; //x is a reference data1.m_value == 2 as well as x.m_value = 2 + testStruct storage x = data1; //x is a reference data1.m_value == 2 as well as x.m_value = 2 data2 = data1; // should copy data. data2.m_value == 2 ret_local = x.m_value; // = 2 @@ -6144,7 +6406,7 @@ BOOST_AUTO_TEST_CASE(struct_delete_member) } function deleteMember() public returns (uint ret_value) { - testStruct x = data1; //should not copy the data. data1.m_value == 2 but x.m_value = 0 + testStruct storage x = data1; //should not copy the data. data1.m_value == 2 but x.m_value = 0 x.m_value = 4; delete x.m_value; ret_value = data1.m_value; @@ -7829,17 +8091,36 @@ BOOST_AUTO_TEST_CASE(multi_variable_declaration) function g() public returns (uint a, uint b, uint c) { a = 1; b = 2; c = 3; } - function f() public returns (bool) { + function h() public returns (uint a, uint b, uint c, uint d) { + a = 1; b = 2; c = 3; d = 4; + } + function f1() public returns (bool) { (uint x, uint y, uint z) = g(); if (x != 1 || y != 2 || z != 3) return false; (, uint a,) = g(); if (a != 2) return false; - (uint b,) = g(); + (uint b, , ) = g(); if (b != 1) return false; - (, uint c) = g(); + (, , uint c) = g(); if (c != 3) return false; return true; } + function f2() public returns (bool) { + (uint a1, , uint a3, ) = h(); + if (a1 != 1 || a3 != 3) return false; + (uint b1, uint b2, , ) = h(); + if (b1 != 1 || b2 != 2) return false; + (, uint c2, uint c3, ) = h(); + if (c2 != 2 || c3 != 3) return false; + (, , uint d3, uint d4) = h(); + if (d3 != 3 || d4 != 4) return false; + (uint e1, , uint e3, uint e4) = h(); + if (e1 != 1 || e3 != 3 || e4 != 4) return false; + return true; + } + function f() public returns (bool) { + return f1() && f2(); + } } )"; compileAndRun(sourceCode); @@ -8611,7 +8892,7 @@ BOOST_AUTO_TEST_CASE(inline_assembly_storage_access_via_pointer) Data public a; uint public separator2; function f() public returns (bool) { - Data x = a; + Data storage x = a; uint off; assembly { sstore(x_slot, 7) @@ -9232,7 +9513,9 @@ BOOST_AUTO_TEST_CASE(break_in_modifier) } } function f() run { - x++; + uint k = x; + uint t = k + 1; + x = t; } } )"; @@ -9242,6 +9525,54 @@ BOOST_AUTO_TEST_CASE(break_in_modifier) ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(1))); } +BOOST_AUTO_TEST_CASE(continue_in_modifier) +{ + char const* sourceCode = R"( + contract C { + uint public x; + modifier run() { + for (uint i = 0; i < 10; i++) { + if (i % 2 == 1) continue; + _; + } + } + function f() run { + uint k = x; + uint t = k + 1; + x = t; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs()); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(5))); +} + +BOOST_AUTO_TEST_CASE(return_in_modifier) +{ + char const* sourceCode = R"( + contract C { + uint public x; + modifier run() { + for (uint i = 1; i < 10; i++) { + if (i == 5) return; + _; + } + } + function f() run { + uint k = x; + uint t = k + 1; + x = t; + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(0))); + ABI_CHECK(callContractFunction("f()"), encodeArgs()); + ABI_CHECK(callContractFunction("x()"), encodeArgs(u256(4))); +} + BOOST_AUTO_TEST_CASE(stacked_return_with_modifiers) { char const* sourceCode = R"( @@ -9254,7 +9585,9 @@ BOOST_AUTO_TEST_CASE(stacked_return_with_modifiers) } } function f() run { - x++; + uint k = x; + uint t = k + 1; + x = t; } } )"; @@ -12173,7 +12506,6 @@ BOOST_AUTO_TEST_CASE(abi_encode_call) BOOST_AUTO_TEST_CASE(staticcall_for_view_and_pure) { char const* sourceCode = R"( - pragma experimental "v0.5.0"; contract C { uint x; function f() public returns (uint) { @@ -12408,6 +12740,43 @@ BOOST_AUTO_TEST_CASE(senders_balance) BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(27))); } +BOOST_AUTO_TEST_CASE(write_storage_external) +{ + char const* sourceCode = R"( + contract C { + uint public x; + function f(uint y) public payable { + x = y; + } + function g(uint y) external { + x = y; + } + function h() public { + this.g(12); + } + } + contract D { + C c = new C(); + function f() public payable returns (uint) { + c.g(3); + return c.x(); + } + function g() public returns (uint) { + c.g(8); + return c.x(); + } + function h() public returns (uint) { + c.h(); + return c.x(); + } + } + )"; + compileAndRun(sourceCode, 0, "D"); + ABI_CHECK(callContractFunction("f()"), encodeArgs(3)); + ABI_CHECK(callContractFunction("g()"), encodeArgs(8)); + ABI_CHECK(callContractFunction("h()"), encodeArgs(12)); +} + BOOST_AUTO_TEST_SUITE_END() } |