mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #1710 from ethereum/strictasmtests
Check error messages for assembly tests.
This commit is contained in:
commit
6bbba106a7
@ -20,14 +20,19 @@
|
|||||||
* Unit tests for inline assembly.
|
* Unit tests for inline assembly.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <string>
|
#include "../TestHelper.h"
|
||||||
#include <memory>
|
|
||||||
#include <libevmasm/Assembly.h>
|
|
||||||
#include <libsolidity/parsing/Scanner.h>
|
|
||||||
#include <libsolidity/inlineasm/AsmStack.h>
|
#include <libsolidity/inlineasm/AsmStack.h>
|
||||||
|
#include <libsolidity/parsing/Scanner.h>
|
||||||
#include <libsolidity/interface/Exceptions.h>
|
#include <libsolidity/interface/Exceptions.h>
|
||||||
#include <libsolidity/ast/AST.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;
|
using namespace std;
|
||||||
|
|
||||||
@ -41,31 +46,44 @@ namespace test
|
|||||||
namespace
|
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;
|
assembly::InlineAssemblyStack stack;
|
||||||
|
bool success = false;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
if (!stack.parse(std::make_shared<Scanner>(CharStream(_source))))
|
success = stack.parse(std::make_shared<Scanner>(CharStream(_source)));
|
||||||
return false;
|
if (success && _assemble)
|
||||||
if (_assemble)
|
|
||||||
{
|
|
||||||
stack.assemble();
|
stack.assemble();
|
||||||
if (!stack.errors().empty())
|
|
||||||
if (!_allowWarnings || !Error::containsOnlyWarnings(stack.errors()))
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (FatalError const&)
|
catch (FatalError const&)
|
||||||
{
|
{
|
||||||
if (Error::containsErrorOfType(stack.errors(), Error::Type::ParserError))
|
BOOST_FAIL("Fatal error leaked.");
|
||||||
return false;
|
success = false;
|
||||||
}
|
}
|
||||||
if (Error::containsErrorOfType(stack.errors(), Error::Type::ParserError))
|
if (!success)
|
||||||
return false;
|
{
|
||||||
|
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()));
|
bool successParse(std::string const& _source, bool _assemble = false, bool _allowWarnings = true)
|
||||||
return true;
|
{
|
||||||
|
return !parseAndReturnFirstError(_source, _assemble, _allowWarnings);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool successAssemble(string const& _source, bool _allowWarnings = true)
|
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);
|
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)
|
void parsePrintCompare(string const& _source)
|
||||||
{
|
{
|
||||||
assembly::InlineAssemblyStack stack;
|
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)
|
BOOST_AUTO_TEST_SUITE(SolidityInlineAssembly)
|
||||||
|
|
||||||
@ -245,7 +286,7 @@ BOOST_AUTO_TEST_CASE(string_literals)
|
|||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(oversize_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)
|
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_AUTO_TEST_CASE(magic_variables)
|
||||||
{
|
{
|
||||||
BOOST_CHECK(!successAssemble("{ this }"));
|
CHECK_ASSEMBLE_ERROR("{ this pop }", DeclarationError, "Identifier not found or not unique");
|
||||||
BOOST_CHECK(!successAssemble("{ ecrecover }"));
|
CHECK_ASSEMBLE_ERROR("{ ecrecover pop }", DeclarationError, "Identifier not found or not unique");
|
||||||
BOOST_CHECK(successAssemble("{ let ecrecover := 1 ecrecover }"));
|
BOOST_CHECK(successAssemble("{ let ecrecover := 1 ecrecover }"));
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(imbalanced_stack)
|
BOOST_AUTO_TEST_CASE(imbalanced_stack)
|
||||||
{
|
{
|
||||||
BOOST_CHECK(successAssemble("{ 1 2 mul pop }", false));
|
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));
|
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)
|
BOOST_AUTO_TEST_CASE(inline_assembly_shadowed_instruction_declaration)
|
||||||
{
|
{
|
||||||
// Error message: "Cannot use instruction names for identifier names."
|
CHECK_ASSEMBLE_ERROR("{ let gas := 1 }", ParserError, "Cannot use instruction names for identifier names.");
|
||||||
BOOST_CHECK(!successAssemble("{ let gas := 1 }"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(inline_assembly_shadowed_instruction_assignment)
|
BOOST_AUTO_TEST_CASE(inline_assembly_shadowed_instruction_assignment)
|
||||||
{
|
{
|
||||||
// Error message: "Identifier expected, got instruction name."
|
CHECK_ASSEMBLE_ERROR("{ 2 =: gas }", ParserError, "Identifier expected, got instruction name.");
|
||||||
BOOST_CHECK(!successAssemble("{ 2 =: gas }"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(inline_assembly_shadowed_instruction_functional_assignment)
|
BOOST_AUTO_TEST_CASE(inline_assembly_shadowed_instruction_functional_assignment)
|
||||||
{
|
{
|
||||||
// Error message: "Cannot use instruction names for identifier names."
|
CHECK_ASSEMBLE_ERROR("{ gas := 2 }", ParserError, "Label name / variable name must precede \":\"");
|
||||||
BOOST_CHECK(!successAssemble("{ gas := 2 }"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(revert)
|
BOOST_AUTO_TEST_CASE(revert)
|
||||||
|
Loading…
Reference in New Issue
Block a user