diff options
Diffstat (limited to 'test/libsolidity/InlineAssembly.cpp')
-rw-r--r-- | test/libsolidity/InlineAssembly.cpp | 99 |
1 files changed, 73 insertions, 26 deletions
diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp index 9035599b..0e9b640a 100644 --- a/test/libsolidity/InlineAssembly.cpp +++ b/test/libsolidity/InlineAssembly.cpp @@ -30,6 +30,7 @@ #include <libevmasm/Assembly.h> #include <boost/optional.hpp> +#include <boost/algorithm/string/replace.hpp> #include <string> #include <memory> @@ -63,7 +64,7 @@ boost::optional<Error> parseAndReturnFirstError(string const& _source, bool _ass } if (!success) { - BOOST_CHECK_EQUAL(stack.errors().size(), 1); + BOOST_REQUIRE_EQUAL(stack.errors().size(), 1); return *stack.errors().front(); } else @@ -137,22 +138,22 @@ BOOST_AUTO_TEST_CASE(smoke_test) BOOST_AUTO_TEST_CASE(simple_instructions) { - BOOST_CHECK(successParse("{ dup1 dup1 mul dup1 sub }")); + BOOST_CHECK(successParse("{ dup1 dup1 mul dup1 sub pop }")); } BOOST_AUTO_TEST_CASE(suicide_selfdestruct) { - BOOST_CHECK(successParse("{ suicide selfdestruct }")); + BOOST_CHECK(successParse("{ 0x01 suicide 0x02 selfdestruct }")); } BOOST_AUTO_TEST_CASE(keywords) { - BOOST_CHECK(successParse("{ byte return address }")); + BOOST_CHECK(successParse("{ 1 2 byte 2 return address pop }")); } BOOST_AUTO_TEST_CASE(constants) { - BOOST_CHECK(successParse("{ 7 8 mul }")); + BOOST_CHECK(successParse("{ 7 8 mul pop }")); } BOOST_AUTO_TEST_CASE(vardecl) @@ -162,37 +163,43 @@ BOOST_AUTO_TEST_CASE(vardecl) BOOST_AUTO_TEST_CASE(assignment) { - BOOST_CHECK(successParse("{ 7 8 add =: x }")); + BOOST_CHECK(successParse("{ let x := 2 7 8 add =: x }")); } BOOST_AUTO_TEST_CASE(label) { - BOOST_CHECK(successParse("{ 7 abc: 8 eq abc jump }")); + BOOST_CHECK(successParse("{ 7 abc: 8 eq abc jump pop }")); } BOOST_AUTO_TEST_CASE(label_complex) { - BOOST_CHECK(successParse("{ 7 abc: 8 eq jump(abc) jumpi(eq(7, 8), abc) }")); + BOOST_CHECK(successParse("{ 7 abc: 8 eq jump(abc) jumpi(eq(7, 8), abc) pop }")); } BOOST_AUTO_TEST_CASE(functional) { - BOOST_CHECK(successParse("{ add(7, mul(6, x)) add mul(7, 8) }")); + BOOST_CHECK(successParse("{ let x := 2 add(7, mul(6, x)) mul(7, 8) add =: x }")); } BOOST_AUTO_TEST_CASE(functional_assignment) { - BOOST_CHECK(successParse("{ x := 7 }")); + BOOST_CHECK(successParse("{ let x := 2 x := 7 }")); } BOOST_AUTO_TEST_CASE(functional_assignment_complex) { - BOOST_CHECK(successParse("{ x := add(7, mul(6, x)) add mul(7, 8) }")); + BOOST_CHECK(successParse("{ let x := 2 x := add(7, mul(6, x)) mul(7, 8) add }")); } BOOST_AUTO_TEST_CASE(vardecl_complex) { - BOOST_CHECK(successParse("{ let x := add(7, mul(6, x)) add mul(7, 8) }")); + BOOST_CHECK(successParse("{ let y := 2 let x := add(7, mul(6, y)) add mul(7, 8) }")); +} + +BOOST_AUTO_TEST_CASE(variable_use_before_decl) +{ + CHECK_PARSE_ERROR("{ x := 2 let x := 3 }", DeclarationError, "Variable x used before it was declared."); + CHECK_PARSE_ERROR("{ let x := mul(2, x) }", DeclarationError, "Variable x used before it was declared."); } BOOST_AUTO_TEST_CASE(blocks) @@ -212,7 +219,28 @@ BOOST_AUTO_TEST_CASE(function_definitions_multiple_args) BOOST_AUTO_TEST_CASE(function_calls) { - BOOST_CHECK(successParse("{ g(1, 2, f(mul(2, 3))) x() }")); + BOOST_CHECK(successParse("{ function f(a) -> (b) {} function g(a, b, c) {} function x() { g(1, 2, f(mul(2, 3))) x() } }")); +} + +BOOST_AUTO_TEST_CASE(opcode_for_functions) +{ + CHECK_PARSE_ERROR("{ function gas() { } }", ParserError, "Cannot use instruction names for identifier names."); +} + +BOOST_AUTO_TEST_CASE(opcode_for_function_args) +{ + CHECK_PARSE_ERROR("{ function f(gas) { } }", ParserError, "Cannot use instruction names for identifier names."); + CHECK_PARSE_ERROR("{ function f() -> (gas) { } }", ParserError, "Cannot use instruction names for identifier names."); +} + +BOOST_AUTO_TEST_CASE(name_clashes) +{ + CHECK_PARSE_ERROR("{ let g := 2 function g() { } }", DeclarationError, "Function name g already taken in this scope"); +} + +BOOST_AUTO_TEST_CASE(variable_access_cross_functions) +{ + CHECK_PARSE_ERROR("{ let x := 2 function g() { x pop } }", DeclarationError, "Identifier not found."); } BOOST_AUTO_TEST_SUITE_END() @@ -226,7 +254,7 @@ BOOST_AUTO_TEST_CASE(print_smoke) BOOST_AUTO_TEST_CASE(print_instructions) { - parsePrintCompare("{\n 7\n 8\n mul\n dup10\n add\n}"); + parsePrintCompare("{\n 7\n 8\n mul\n dup10\n add\n pop\n}"); } BOOST_AUTO_TEST_CASE(print_subblock) @@ -236,7 +264,7 @@ BOOST_AUTO_TEST_CASE(print_subblock) BOOST_AUTO_TEST_CASE(print_functional) { - parsePrintCompare("{\n mul(sload(0x12), 7)\n}"); + parsePrintCompare("{\n let x := mul(sload(0x12), 7)\n}"); } BOOST_AUTO_TEST_CASE(print_label) @@ -251,13 +279,13 @@ BOOST_AUTO_TEST_CASE(print_assignments) BOOST_AUTO_TEST_CASE(print_string_literals) { - parsePrintCompare("{\n \"\\n'\\xab\\x95\\\"\"\n}"); + parsePrintCompare("{\n \"\\n'\\xab\\x95\\\"\"\n pop\n}"); } BOOST_AUTO_TEST_CASE(print_string_literal_unicode) { - string source = "{ \"\\u1bac\" }"; - string parsed = "{\n \"\\xe1\\xae\\xac\"\n}"; + string source = "{ let x := \"\\u1bac\" }"; + string parsed = "{\n let x := \"\\xe1\\xae\\xac\"\n}"; assembly::InlineAssemblyStack stack; BOOST_REQUIRE(stack.parse(std::make_shared<Scanner>(CharStream(source)))); BOOST_REQUIRE(stack.errors().empty()); @@ -272,7 +300,21 @@ BOOST_AUTO_TEST_CASE(function_definitions_multiple_args) BOOST_AUTO_TEST_CASE(function_calls) { - parsePrintCompare("{\n g(1, mul(2, x), f(mul(2, 3)))\n x()\n}"); + string source = R"({ + function y() + { + } + function f(a) -> (b) + { + } + function g(a, b, c) + { + } + g(1, mul(2, address), f(mul(2, caller))) + y() +})"; + boost::replace_all(source, "\t", " "); + parsePrintCompare(source); } BOOST_AUTO_TEST_SUITE_END() @@ -291,27 +333,32 @@ BOOST_AUTO_TEST_CASE(oversize_string_literals) BOOST_AUTO_TEST_CASE(assignment_after_tag) { - BOOST_CHECK(successParse("{ let x := 1 { tag: =: x } }")); + BOOST_CHECK(successParse("{ let x := 1 { 7 tag: =: x } }")); } BOOST_AUTO_TEST_CASE(magic_variables) { - CHECK_ASSEMBLE_ERROR("{ this pop }", DeclarationError, "Identifier not found or not unique"); - CHECK_ASSEMBLE_ERROR("{ ecrecover pop }", DeclarationError, "Identifier not found or not unique"); - BOOST_CHECK(successAssemble("{ let ecrecover := 1 ecrecover }")); + CHECK_ASSEMBLE_ERROR("{ this pop }", DeclarationError, "Identifier not found"); + CHECK_ASSEMBLE_ERROR("{ ecrecover pop }", DeclarationError, "Identifier not found"); + BOOST_CHECK(successAssemble("{ let ecrecover := 1 ecrecover pop }")); +} + +BOOST_AUTO_TEST_CASE(stack_variables) +{ + BOOST_CHECK(successAssemble("{ let y := 3 { 2 { let x := y } pop} }")); } BOOST_AUTO_TEST_CASE(imbalanced_stack) { BOOST_CHECK(successAssemble("{ 1 2 mul pop }", false)); - CHECK_ASSEMBLE_ERROR("{ 1 }", Warning, "Inline assembly block is not balanced. It leaves"); - CHECK_ASSEMBLE_ERROR("{ pop }", Warning, "Inline assembly block is not balanced. It takes"); + CHECK_ASSEMBLE_ERROR("{ 1 }", DeclarationError, "Unbalanced stack at the end of a block: 1 surplus item(s)."); + CHECK_ASSEMBLE_ERROR("{ pop }", DeclarationError, "Unbalanced stack at the end of a block: 1 missing item(s)."); BOOST_CHECK(successAssemble("{ let x := 4 7 add }", false)); } BOOST_AUTO_TEST_CASE(error_tag) { - BOOST_CHECK(successAssemble("{ invalidJumpLabel }")); + BOOST_CHECK(successAssemble("{ jump(invalidJumpLabel) }")); } BOOST_AUTO_TEST_CASE(designated_invalid_instruction) |