aboutsummaryrefslogtreecommitdiffstats
path: root/test/libsolidity
diff options
context:
space:
mode:
Diffstat (limited to 'test/libsolidity')
-rw-r--r--test/libsolidity/InlineAssembly.cpp99
1 files changed, 69 insertions, 30 deletions
diff --git a/test/libsolidity/InlineAssembly.cpp b/test/libsolidity/InlineAssembly.cpp
index ddbc3c63..9035599b 100644
--- a/test/libsolidity/InlineAssembly.cpp
+++ b/test/libsolidity/InlineAssembly.cpp
@@ -20,14 +20,19 @@
* Unit tests for inline assembly.
*/
-#include <string>
-#include <memory>
-#include <libevmasm/Assembly.h>
-#include <libsolidity/parsing/Scanner.h>
+#include "../TestHelper.h"
+
#include <libsolidity/inlineasm/AsmStack.h>
+#include <libsolidity/parsing/Scanner.h>
#include <libsolidity/interface/Exceptions.h>
#include <libsolidity/ast/AST.h>
-#include "../TestHelper.h"
+#include <test/libsolidity/ErrorCheck.h>
+#include <libevmasm/Assembly.h>
+
+#include <boost/optional.hpp>
+
+#include <string>
+#include <memory>
using namespace std;
@@ -41,31 +46,44 @@ namespace test
namespace
{
-bool successParse(std::string const& _source, bool _assemble = false, bool _allowWarnings = true)
+boost::optional<Error> parseAndReturnFirstError(string const& _source, bool _assemble = false, bool _allowWarnings = true)
{
assembly::InlineAssemblyStack stack;
+ bool success = false;
try
{
- if (!stack.parse(std::make_shared<Scanner>(CharStream(_source))))
- return false;
- if (_assemble)
- {
+ success = stack.parse(std::make_shared<Scanner>(CharStream(_source)));
+ if (success && _assemble)
stack.assemble();
- if (!stack.errors().empty())
- if (!_allowWarnings || !Error::containsOnlyWarnings(stack.errors()))
- return false;
- }
}
catch (FatalError const&)
{
- if (Error::containsErrorOfType(stack.errors(), Error::Type::ParserError))
- return false;
+ BOOST_FAIL("Fatal error leaked.");
+ success = false;
}
- if (Error::containsErrorOfType(stack.errors(), Error::Type::ParserError))
- return false;
+ if (!success)
+ {
+ BOOST_CHECK_EQUAL(stack.errors().size(), 1);
+ return *stack.errors().front();
+ }
+ else
+ {
+ // If success is true, there might still be an error in the assembly stage.
+ if (_allowWarnings && Error::containsOnlyWarnings(stack.errors()))
+ return {};
+ else if (!stack.errors().empty())
+ {
+ if (!_allowWarnings)
+ BOOST_CHECK_EQUAL(stack.errors().size(), 1);
+ return *stack.errors().front();
+ }
+ }
+ return {};
+}
- BOOST_CHECK(Error::containsOnlyWarnings(stack.errors()));
- return true;
+bool successParse(std::string const& _source, bool _assemble = false, bool _allowWarnings = true)
+{
+ return !parseAndReturnFirstError(_source, _assemble, _allowWarnings);
}
bool successAssemble(string const& _source, bool _allowWarnings = true)
@@ -73,6 +91,14 @@ bool successAssemble(string const& _source, bool _allowWarnings = true)
return successParse(_source, true, _allowWarnings);
}
+Error expectError(std::string const& _source, bool _assemble, bool _allowWarnings = false)
+{
+
+ auto error = parseAndReturnFirstError(_source, _assemble, _allowWarnings);
+ BOOST_REQUIRE(error);
+ return *error;
+}
+
void parsePrintCompare(string const& _source)
{
assembly::InlineAssemblyStack stack;
@@ -83,6 +109,21 @@ void parsePrintCompare(string const& _source)
}
+#define CHECK_ERROR(text, assemble, typ, substring) \
+do \
+{ \
+ Error err = expectError((text), (assemble), false); \
+ BOOST_CHECK(err.type() == (Error::Type::typ)); \
+ BOOST_CHECK(searchErrorMessage(err, (substring))); \
+} while(0)
+
+#define CHECK_PARSE_ERROR(text, type, substring) \
+CHECK_ERROR(text, false, type, substring)
+
+#define CHECK_ASSEMBLE_ERROR(text, type, substring) \
+CHECK_ERROR(text, true, type, substring)
+
+
BOOST_AUTO_TEST_SUITE(SolidityInlineAssembly)
@@ -245,7 +286,7 @@ BOOST_AUTO_TEST_CASE(string_literals)
BOOST_AUTO_TEST_CASE(oversize_string_literals)
{
- BOOST_CHECK(!successAssemble("{ let x := \"123456789012345678901234567890123\" }"));
+ CHECK_ASSEMBLE_ERROR("{ let x := \"123456789012345678901234567890123\" }", TypeError, "String literal too long");
}
BOOST_AUTO_TEST_CASE(assignment_after_tag)
@@ -255,15 +296,16 @@ BOOST_AUTO_TEST_CASE(assignment_after_tag)
BOOST_AUTO_TEST_CASE(magic_variables)
{
- BOOST_CHECK(!successAssemble("{ this }"));
- BOOST_CHECK(!successAssemble("{ ecrecover }"));
+ 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 }"));
}
BOOST_AUTO_TEST_CASE(imbalanced_stack)
{
BOOST_CHECK(successAssemble("{ 1 2 mul pop }", false));
- BOOST_CHECK(!successAssemble("{ 1 }", 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");
BOOST_CHECK(successAssemble("{ let x := 4 7 add }", false));
}
@@ -279,20 +321,17 @@ BOOST_AUTO_TEST_CASE(designated_invalid_instruction)
BOOST_AUTO_TEST_CASE(inline_assembly_shadowed_instruction_declaration)
{
- // Error message: "Cannot use instruction names for identifier names."
- BOOST_CHECK(!successAssemble("{ let gas := 1 }"));
+ CHECK_ASSEMBLE_ERROR("{ let gas := 1 }", ParserError, "Cannot use instruction names for identifier names.");
}
BOOST_AUTO_TEST_CASE(inline_assembly_shadowed_instruction_assignment)
{
- // Error message: "Identifier expected, got instruction name."
- BOOST_CHECK(!successAssemble("{ 2 =: gas }"));
+ CHECK_ASSEMBLE_ERROR("{ 2 =: gas }", ParserError, "Identifier expected, got instruction name.");
}
BOOST_AUTO_TEST_CASE(inline_assembly_shadowed_instruction_functional_assignment)
{
- // Error message: "Cannot use instruction names for identifier names."
- BOOST_CHECK(!successAssemble("{ gas := 2 }"));
+ CHECK_ASSEMBLE_ERROR("{ gas := 2 }", ParserError, "Label name / variable name must precede \":\"");
}
BOOST_AUTO_TEST_CASE(revert)