mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Adds support for tuples in test file parser.
This commit is contained in:
parent
161b22bd13
commit
c9c4578023
@ -31,6 +31,7 @@ using namespace langutil;
|
||||
using namespace solidity;
|
||||
using namespace dev::solidity::test;
|
||||
using namespace std;
|
||||
using namespace soltest;
|
||||
|
||||
namespace
|
||||
{
|
||||
@ -47,14 +48,14 @@ namespace
|
||||
vector<dev::solidity::test::FunctionCall> TestFileParser::parseFunctionCalls()
|
||||
{
|
||||
vector<FunctionCall> calls;
|
||||
if (!accept(SoltToken::EOS))
|
||||
if (!accept(Token::EOS))
|
||||
{
|
||||
assert(m_scanner.currentToken() == SoltToken::Unknown);
|
||||
assert(m_scanner.currentToken() == Token::Unknown);
|
||||
m_scanner.scanNextToken();
|
||||
|
||||
while (!accept(SoltToken::EOS))
|
||||
while (!accept(Token::EOS))
|
||||
{
|
||||
if (!accept(SoltToken::Whitespace))
|
||||
if (!accept(Token::Whitespace))
|
||||
{
|
||||
FunctionCall call;
|
||||
|
||||
@ -64,63 +65,47 @@ vector<dev::solidity::test::FunctionCall> TestFileParser::parseFunctionCalls()
|
||||
/// token lookahead that checks parseParameter
|
||||
/// if the next token is an identifier.
|
||||
if (calls.empty())
|
||||
expect(SoltToken::Newline);
|
||||
expect(Token::Newline);
|
||||
else
|
||||
accept(SoltToken::Newline, true);
|
||||
accept(Token::Newline, true);
|
||||
|
||||
call.signature = parseFunctionSignature();
|
||||
if (accept(SoltToken::Comma, true))
|
||||
if (accept(Token::Comma, true))
|
||||
call.value = parseFunctionCallValue();
|
||||
if (accept(SoltToken::Colon, true))
|
||||
if (accept(Token::Colon, true))
|
||||
call.arguments = parseFunctionCallArguments();
|
||||
|
||||
if (accept(SoltToken::Newline, true))
|
||||
if (accept(Token::Newline, true))
|
||||
call.displayMode = FunctionCall::DisplayMode::MultiLine;
|
||||
|
||||
call.arguments.comment = parseComment();
|
||||
|
||||
if (accept(SoltToken::Newline, true))
|
||||
if (accept(Token::Newline, true))
|
||||
call.displayMode = FunctionCall::DisplayMode::MultiLine;
|
||||
|
||||
expect(SoltToken::Arrow);
|
||||
expect(Token::Arrow);
|
||||
call.expectations = parseFunctionCallExpectations();
|
||||
call.expectations.comment = parseComment();
|
||||
|
||||
calls.emplace_back(std::move(call));
|
||||
}
|
||||
else
|
||||
m_scanner.scanNextToken();
|
||||
}
|
||||
}
|
||||
return calls;
|
||||
}
|
||||
|
||||
string TestFileParser::formatToken(SoltToken _token)
|
||||
{
|
||||
switch (_token)
|
||||
{
|
||||
#define T(name, string, precedence) case SoltToken::name: return string;
|
||||
SOLT_TOKEN_LIST(T, T)
|
||||
#undef T
|
||||
default: // Token::NUM_TOKENS:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
bool TestFileParser::accept(SoltToken _token, bool const _expect)
|
||||
{
|
||||
if (m_scanner.currentToken() == _token)
|
||||
{
|
||||
if (_expect)
|
||||
expect(_token);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool TestFileParser::expect(SoltToken _token, bool const _advance)
|
||||
bool TestFileParser::accept(soltest::Token _token, bool const _expect)
|
||||
{
|
||||
if (m_scanner.currentToken() != _token)
|
||||
return false;
|
||||
if (_expect)
|
||||
return expect(_token);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool TestFileParser::expect(soltest::Token _token, bool const _advance)
|
||||
{
|
||||
if (m_scanner.currentToken() != _token || m_scanner.currentToken() == Token::Invalid)
|
||||
throw Error(
|
||||
Error::Type::ParserError,
|
||||
"Unexpected " + formatToken(m_scanner.currentToken()) + ": \"" +
|
||||
@ -135,32 +120,35 @@ bool TestFileParser::expect(SoltToken _token, bool const _advance)
|
||||
string TestFileParser::parseFunctionSignature()
|
||||
{
|
||||
string signature = m_scanner.currentLiteral();
|
||||
expect(SoltToken::Identifier);
|
||||
expect(Token::Identifier);
|
||||
|
||||
signature += formatToken(SoltToken::LParen);
|
||||
expect(SoltToken::LParen);
|
||||
signature += formatToken(Token::LParen);
|
||||
expect(Token::LParen);
|
||||
|
||||
while (!accept(SoltToken::RParen))
|
||||
string parameters;
|
||||
if (!accept(Token::RParen, false))
|
||||
parameters = parseIdentifierOrTuple();
|
||||
|
||||
while (accept(Token::Comma))
|
||||
{
|
||||
signature += m_scanner.currentLiteral();
|
||||
expect(SoltToken::Identifier);
|
||||
while (accept(SoltToken::Comma))
|
||||
{
|
||||
signature += m_scanner.currentLiteral();
|
||||
expect(SoltToken::Comma);
|
||||
signature += m_scanner.currentLiteral();
|
||||
expect(SoltToken::Identifier);
|
||||
}
|
||||
parameters += formatToken(Token::Comma);
|
||||
expect(Token::Comma);
|
||||
parameters += parseIdentifierOrTuple();
|
||||
}
|
||||
signature += formatToken(SoltToken::RParen);
|
||||
expect(SoltToken::RParen);
|
||||
if (accept(Token::Arrow, true))
|
||||
throw Error(Error::Type::ParserError, "Invalid signature detected: " + signature);
|
||||
|
||||
signature += parameters;
|
||||
|
||||
expect(Token::RParen);
|
||||
signature += formatToken(Token::RParen);
|
||||
return signature;
|
||||
}
|
||||
|
||||
u256 TestFileParser::parseFunctionCallValue()
|
||||
{
|
||||
u256 value = convertNumber(parseNumber());
|
||||
expect(SoltToken::Ether);
|
||||
expect(Token::Ether);
|
||||
return value;
|
||||
}
|
||||
|
||||
@ -173,7 +161,7 @@ FunctionCallArgs TestFileParser::parseFunctionCallArguments()
|
||||
throw Error(Error::Type::ParserError, "No argument provided.");
|
||||
arguments.parameters.emplace_back(param);
|
||||
|
||||
while (accept(SoltToken::Comma, true))
|
||||
while (accept(Token::Comma, true))
|
||||
arguments.parameters.emplace_back(parseParameter());
|
||||
return arguments;
|
||||
}
|
||||
@ -190,7 +178,7 @@ FunctionCallExpectations TestFileParser::parseFunctionCallExpectations()
|
||||
}
|
||||
expectations.result.emplace_back(param);
|
||||
|
||||
while (accept(SoltToken::Comma, true))
|
||||
while (accept(Token::Comma, true))
|
||||
expectations.result.emplace_back(parseParameter());
|
||||
|
||||
/// We have always one virtual parameter in the parameter list.
|
||||
@ -203,7 +191,7 @@ FunctionCallExpectations TestFileParser::parseFunctionCallExpectations()
|
||||
Parameter TestFileParser::parseParameter()
|
||||
{
|
||||
Parameter parameter;
|
||||
if (accept(SoltToken::Newline, true))
|
||||
if (accept(Token::Newline, true))
|
||||
parameter.format.newline = true;
|
||||
auto literal = parseABITypeLiteral();
|
||||
parameter.rawBytes = literal.first;
|
||||
@ -218,20 +206,20 @@ pair<bytes, ABIType> TestFileParser::parseABITypeLiteral()
|
||||
u256 number{0};
|
||||
ABIType abiType{ABIType::None, 0};
|
||||
|
||||
if (accept(SoltToken::Sub))
|
||||
if (accept(Token::Sub))
|
||||
{
|
||||
abiType = ABIType{ABIType::SignedDec, 32};
|
||||
expect(SoltToken::Sub);
|
||||
expect(Token::Sub);
|
||||
number = convertNumber(parseNumber()) * -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (accept(SoltToken::Number))
|
||||
if (accept(Token::Number))
|
||||
{
|
||||
abiType = ABIType{ABIType::UnsignedDec, 32};
|
||||
number = convertNumber(parseNumber());
|
||||
}
|
||||
else if (accept(SoltToken::Failure, true))
|
||||
else if (accept(Token::Failure, true))
|
||||
{
|
||||
abiType = ABIType{ABIType::Failure, 0};
|
||||
return make_pair(bytes{}, abiType);
|
||||
@ -245,10 +233,35 @@ pair<bytes, ABIType> TestFileParser::parseABITypeLiteral()
|
||||
}
|
||||
}
|
||||
|
||||
string TestFileParser::parseIdentifierOrTuple()
|
||||
{
|
||||
string identOrTuple;
|
||||
|
||||
if (accept(Token::Identifier))
|
||||
{
|
||||
identOrTuple = m_scanner.currentLiteral();
|
||||
expect(Token::Identifier);
|
||||
return identOrTuple;
|
||||
}
|
||||
expect(Token::LParen);
|
||||
identOrTuple += formatToken(Token::LParen);
|
||||
identOrTuple += parseIdentifierOrTuple();
|
||||
|
||||
while (accept(Token::Comma))
|
||||
{
|
||||
identOrTuple += formatToken(Token::Comma);
|
||||
expect(Token::Comma);
|
||||
identOrTuple += parseIdentifierOrTuple();
|
||||
}
|
||||
expect(Token::RParen);
|
||||
identOrTuple += formatToken(Token::RParen);
|
||||
return identOrTuple;
|
||||
}
|
||||
|
||||
string TestFileParser::parseComment()
|
||||
{
|
||||
string comment = m_scanner.currentLiteral();
|
||||
if (accept(SoltToken::Comment, true))
|
||||
if (accept(Token::Comment, true))
|
||||
return comment;
|
||||
return string{};
|
||||
}
|
||||
@ -256,7 +269,7 @@ string TestFileParser::parseComment()
|
||||
string TestFileParser::parseNumber()
|
||||
{
|
||||
string literal = m_scanner.currentLiteral();
|
||||
expect(SoltToken::Number);
|
||||
expect(Token::Number);
|
||||
return literal;
|
||||
}
|
||||
|
||||
@ -281,18 +294,21 @@ void TestFileParser::Scanner::readStream(istream& _stream)
|
||||
|
||||
void TestFileParser::Scanner::scanNextToken()
|
||||
{
|
||||
auto detectToken = [](std::string const& _literal = "") -> TokenDesc {
|
||||
if (_literal == "ether") return TokenDesc{SoltToken::Ether, _literal};
|
||||
if (_literal == "FAILURE") return TokenDesc{SoltToken::Failure, _literal};
|
||||
return TokenDesc{SoltToken::Identifier, _literal};
|
||||
// Make code coverage happy.
|
||||
assert(formatToken(Token::NUM_TOKENS) == "");
|
||||
|
||||
auto detectKeyword = [](std::string const& _literal = "") -> TokenDesc {
|
||||
if (_literal == "ether") return TokenDesc{Token::Ether, _literal};
|
||||
if (_literal == "FAILURE") return TokenDesc{Token::Failure, _literal};
|
||||
return TokenDesc{Token::Identifier, _literal};
|
||||
};
|
||||
|
||||
auto selectToken = [this](SoltToken _token, std::string const& _literal = "") -> TokenDesc {
|
||||
auto selectToken = [this](Token _token, std::string const& _literal = "") -> TokenDesc {
|
||||
advance();
|
||||
return make_pair(_token, !_literal.empty() ? _literal : formatToken(_token));
|
||||
};
|
||||
|
||||
TokenDesc token = make_pair(SoltToken::Unknown, "");
|
||||
TokenDesc token = make_pair(Token::Unknown, "");
|
||||
do
|
||||
{
|
||||
switch(current())
|
||||
@ -300,50 +316,50 @@ void TestFileParser::Scanner::scanNextToken()
|
||||
case '/':
|
||||
advance();
|
||||
if (current() == '/')
|
||||
token = selectToken(SoltToken::Newline);
|
||||
token = selectToken(Token::Newline);
|
||||
else
|
||||
token = selectToken(Token::Invalid);
|
||||
break;
|
||||
case '-':
|
||||
if (peek() == '>')
|
||||
{
|
||||
advance();
|
||||
token = selectToken(SoltToken::Arrow);
|
||||
token = selectToken(Token::Arrow);
|
||||
}
|
||||
else
|
||||
token = selectToken(SoltToken::Sub);
|
||||
token = selectToken(Token::Sub);
|
||||
break;
|
||||
case ':':
|
||||
token = selectToken(SoltToken::Colon);
|
||||
token = selectToken(Token::Colon);
|
||||
break;
|
||||
case '#':
|
||||
token = selectToken(SoltToken::Comment, scanComment());
|
||||
token = selectToken(Token::Comment, scanComment());
|
||||
break;
|
||||
case ',':
|
||||
token = selectToken(SoltToken::Comma);
|
||||
token = selectToken(Token::Comma);
|
||||
break;
|
||||
case '(':
|
||||
token = selectToken(SoltToken::LParen);
|
||||
token = selectToken(Token::LParen);
|
||||
break;
|
||||
case ')':
|
||||
token = selectToken(SoltToken::RParen);
|
||||
token = selectToken(Token::RParen);
|
||||
break;
|
||||
default:
|
||||
if (isIdentifierStart(current()))
|
||||
{
|
||||
TokenDesc detectedToken = detectToken(scanIdentifierOrKeyword());
|
||||
TokenDesc detectedToken = detectKeyword(scanIdentifierOrKeyword());
|
||||
token = selectToken(detectedToken.first, detectedToken.second);
|
||||
}
|
||||
else if (isdigit(current()))
|
||||
token = selectToken(SoltToken::Number, scanNumber());
|
||||
token = selectToken(Token::Number, scanNumber());
|
||||
else if (isspace(current()))
|
||||
token = selectToken(SoltToken::Whitespace);
|
||||
token = selectToken(Token::Whitespace);
|
||||
else if (isEndOfLine())
|
||||
token = selectToken(SoltToken::EOS);
|
||||
else
|
||||
token = selectToken(SoltToken::Invalid);
|
||||
token = selectToken(Token::EOS);
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (token.first == SoltToken::Whitespace);
|
||||
while (token.first == Token::Whitespace);
|
||||
m_currentToken = token;
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@ namespace test
|
||||
{
|
||||
|
||||
/**
|
||||
* All SOLT (or SOLTest) tokens.
|
||||
* All soltest tokens.
|
||||
*/
|
||||
#define SOLT_TOKEN_LIST(T, K) \
|
||||
T(Unknown, "unknown", 0) \
|
||||
@ -62,12 +62,30 @@ namespace test
|
||||
/* special keywords */ \
|
||||
K(Failure, "FAILURE", 0) \
|
||||
|
||||
enum class SoltToken : unsigned int {
|
||||
#define T(name, string, precedence) name,
|
||||
SOLT_TOKEN_LIST(T, T)
|
||||
NUM_TOKENS
|
||||
#undef T
|
||||
};
|
||||
namespace soltest
|
||||
{
|
||||
enum class Token : unsigned int {
|
||||
#define T(name, string, precedence) name,
|
||||
SOLT_TOKEN_LIST(T, T)
|
||||
NUM_TOKENS
|
||||
#undef T
|
||||
};
|
||||
|
||||
/// Prints a friendly string representation of \param _token.
|
||||
inline std::string formatToken(Token _token)
|
||||
{
|
||||
switch (_token)
|
||||
{
|
||||
#define T(name, string, precedence) case Token::name: return string;
|
||||
SOLT_TOKEN_LIST(T, T)
|
||||
#undef T
|
||||
default: // Token::NUM_TOKENS:
|
||||
return "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* The purpose of the ABI type is the storage of type information
|
||||
@ -92,7 +110,7 @@ struct ABIType
|
||||
|
||||
/**
|
||||
* Helper that can hold format information retrieved
|
||||
* while scanning through a parameter list in sol_t.
|
||||
* while scanning through a parameter list in soltest.
|
||||
*/
|
||||
struct FormatInfo
|
||||
{
|
||||
@ -133,7 +151,7 @@ using ParameterList = std::vector<Parameter>;
|
||||
*/
|
||||
struct FunctionCallExpectations
|
||||
{
|
||||
/// Representation of the comma-separated (or empty) list of expectated result values
|
||||
/// Representation of the comma-separated (or empty) list of expected result values
|
||||
/// attached to the function call object. It is checked against the actual result of
|
||||
/// a function call when used in test framework.
|
||||
ParameterList result;
|
||||
@ -237,10 +255,8 @@ public:
|
||||
/// of its arguments or expected results.
|
||||
std::vector<FunctionCall> parseFunctionCalls();
|
||||
|
||||
/// Prints a friendly string representation of \param _token.
|
||||
static std::string formatToken(SoltToken _token);
|
||||
|
||||
private:
|
||||
using Token = soltest::Token;
|
||||
/**
|
||||
* Token scanner that is used internally to abstract away character traversal.
|
||||
*/
|
||||
@ -257,7 +273,7 @@ private:
|
||||
/// Reads character stream and creates token.
|
||||
void scanNextToken();
|
||||
|
||||
SoltToken currentToken() { return m_currentToken.first; }
|
||||
soltest::Token currentToken() { return m_currentToken.first; }
|
||||
std::string currentLiteral() { return m_currentToken.second; }
|
||||
|
||||
std::string scanComment();
|
||||
@ -265,7 +281,7 @@ private:
|
||||
std::string scanNumber();
|
||||
|
||||
private:
|
||||
using TokenDesc = std::pair<SoltToken, std::string>;
|
||||
using TokenDesc = std::pair<Token, std::string>;
|
||||
|
||||
/// Advances current position in the input stream.
|
||||
void advance() { ++m_char; }
|
||||
@ -284,8 +300,8 @@ private:
|
||||
TokenDesc m_currentToken;
|
||||
};
|
||||
|
||||
bool accept(SoltToken _token, bool const _expect = false);
|
||||
bool expect(SoltToken _token, bool const _advance = true);
|
||||
bool accept(soltest::Token _token, bool const _expect = false);
|
||||
bool expect(soltest::Token _token, bool const _advance = true);
|
||||
|
||||
/// Parses a function call signature in the form of f(uint256, ...).
|
||||
std::string parseFunctionSignature();
|
||||
@ -319,7 +335,12 @@ private:
|
||||
/// if data type is not supported.
|
||||
std::pair<bytes, ABIType> parseABITypeLiteral();
|
||||
|
||||
/// Parses a comment
|
||||
/// Recursively parses an identifier or a tuple definition that contains identifiers
|
||||
/// and / or parentheses like `((uint, uint), (uint, (uint, uint)), uint)`.
|
||||
std::string parseIdentifierOrTuple();
|
||||
|
||||
/// Parses a comment that is defined like this:
|
||||
/// # A nice comment. #
|
||||
std::string parseComment();
|
||||
|
||||
/// Parses the current number literal.
|
||||
|
@ -265,6 +265,61 @@ BOOST_AUTO_TEST_CASE(call_arguments)
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(call_arguments_tuple)
|
||||
{
|
||||
char const* source = R"(
|
||||
// f((uint256, bytes32), uint256) ->
|
||||
// f((uint8), uint8) ->
|
||||
)";
|
||||
auto const calls = parse(source);
|
||||
BOOST_REQUIRE_EQUAL(calls.size(), 2);
|
||||
testFunctionCall(calls.at(0), Mode::SingleLine, "f((uint256,bytes32),uint256)", false);
|
||||
testFunctionCall(calls.at(1), Mode::SingleLine, "f((uint8),uint8)", false);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(call_arguments_tuple_of_tuples)
|
||||
{
|
||||
char const* source = R"(
|
||||
// f(((uint256, bytes32), bytes32), uint256)
|
||||
// # f(S memory s, uint256 b) #
|
||||
// ->
|
||||
)";
|
||||
auto const calls = parse(source);
|
||||
BOOST_REQUIRE_EQUAL(calls.size(), 1);
|
||||
testFunctionCall(
|
||||
calls.at(0),
|
||||
Mode::MultiLine,
|
||||
"f(((uint256,bytes32),bytes32),uint256)",
|
||||
false,
|
||||
fmt::encodeArgs(),
|
||||
fmt::encodeArgs(),
|
||||
0,
|
||||
" f(S memory s, uint256 b) "
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(call_arguments_recursive_tuples)
|
||||
{
|
||||
char const* source = R"(
|
||||
// f(((((bytes, bytes, bytes), bytes), bytes), bytes), bytes) ->
|
||||
// f(((((bytes, bytes, (bytes)), bytes), bytes), (bytes, bytes)), (bytes, bytes)) ->
|
||||
)";
|
||||
auto const calls = parse(source);
|
||||
BOOST_REQUIRE_EQUAL(calls.size(), 2);
|
||||
testFunctionCall(
|
||||
calls.at(0),
|
||||
Mode::SingleLine,
|
||||
"f(((((bytes,bytes,bytes),bytes),bytes),bytes),bytes)",
|
||||
false
|
||||
);
|
||||
testFunctionCall(
|
||||
calls.at(1),
|
||||
Mode::SingleLine,
|
||||
"f(((((bytes,bytes,(bytes)),bytes),bytes),(bytes,bytes)),(bytes,bytes))",
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(call_arguments_mismatch)
|
||||
{
|
||||
char const* source = R"(
|
||||
@ -333,18 +388,58 @@ BOOST_AUTO_TEST_CASE(call_signature)
|
||||
char const* source = R"(
|
||||
// f(uint256, uint8, string) -> FAILURE
|
||||
// f(invalid, xyz, foo) -> FAILURE
|
||||
)";
|
||||
)";
|
||||
auto const calls = parse(source);
|
||||
BOOST_REQUIRE_EQUAL(calls.size(), 2);
|
||||
testFunctionCall(calls.at(0), Mode::SingleLine, "f(uint256,uint8,string)", true);
|
||||
testFunctionCall(calls.at(1), Mode::SingleLine, "f(invalid,xyz,foo)", true);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(call_newline_invalid)
|
||||
{
|
||||
char const* source = R"(
|
||||
/
|
||||
)";
|
||||
BOOST_REQUIRE_THROW(parse(source), langutil::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(call_invalid)
|
||||
{
|
||||
char const* source = R"(
|
||||
/ f() ->
|
||||
)";
|
||||
BOOST_REQUIRE_THROW(parse(source), langutil::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(call_signature_invalid)
|
||||
{
|
||||
char const* source = R"(
|
||||
// f(uint8,) -> FAILURE
|
||||
)";
|
||||
)";
|
||||
BOOST_REQUIRE_THROW(parse(source), langutil::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(call_arguments_tuple_invalid)
|
||||
{
|
||||
char const* source = R"(
|
||||
// f((uint8,) -> FAILURE
|
||||
)";
|
||||
BOOST_REQUIRE_THROW(parse(source), langutil::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(call_arguments_tuple_invalid_empty)
|
||||
{
|
||||
char const* source = R"(
|
||||
// f(uint8, ()) -> FAILURE
|
||||
)";
|
||||
BOOST_REQUIRE_THROW(parse(source), langutil::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(call_arguments_tuple_invalid_parantheses)
|
||||
{
|
||||
char const* source = R"(
|
||||
// f((uint8,() -> FAILURE
|
||||
)";
|
||||
BOOST_REQUIRE_THROW(parse(source), langutil::Error);
|
||||
}
|
||||
|
||||
@ -370,6 +465,14 @@ BOOST_AUTO_TEST_CASE(call_arguments_invalid)
|
||||
BOOST_REQUIRE_THROW(parse(source), langutil::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(call_arguments_invalid_decimal)
|
||||
{
|
||||
char const* source = R"(
|
||||
// sig(): 0.h3 ->
|
||||
)";
|
||||
BOOST_REQUIRE_THROW(parse(source), langutil::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(call_ether_value_invalid)
|
||||
{
|
||||
char const* source = R"(
|
||||
@ -378,6 +481,14 @@ BOOST_AUTO_TEST_CASE(call_ether_value_invalid)
|
||||
BOOST_REQUIRE_THROW(parse(source), langutil::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(call_ether_value_invalid_decimal)
|
||||
{
|
||||
char const* source = R"(
|
||||
// sig(): 0.1hd ether ->
|
||||
)";
|
||||
BOOST_REQUIRE_THROW(parse(source), langutil::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(call_ether_type_invalid)
|
||||
{
|
||||
char const* source = R"(
|
||||
@ -405,6 +516,14 @@ BOOST_AUTO_TEST_CASE(call_arguments_newline_colon)
|
||||
BOOST_REQUIRE_THROW(parse(source), langutil::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(call_arrow_missing)
|
||||
{
|
||||
char const* source = R"(
|
||||
// h256()
|
||||
)";
|
||||
BOOST_REQUIRE_THROW(parse(source), langutil::Error);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_SUITE_END()
|
||||
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user