Skip to content

Commit f5fa62d

Browse files
committed
Cleans up test file parser and its tests.
1 parent f881702 commit f5fa62d

File tree

3 files changed

+295
-213
lines changed

3 files changed

+295
-213
lines changed

test/libsolidity/util/TestFileParser.cpp

+39-45
Original file line numberDiff line numberDiff line change
@@ -34,21 +34,13 @@ using namespace std;
3434

3535
namespace
3636
{
37-
bool isDecimalDigit(char c)
38-
{
39-
return '0' <= c && c <= '9';
40-
}
41-
bool isWhiteSpace(char c)
42-
{
43-
return c == ' ' || c == '\n' || c == '\t' || c == '\r';
44-
}
4537
bool isIdentifierStart(char c)
4638
{
4739
return c == '_' || c == '$' || ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z');
4840
}
4941
bool isIdentifierPart(char c)
5042
{
51-
return isIdentifierStart(c) || isDecimalDigit(c);
43+
return isIdentifierStart(c) || isdigit(c);
5244
}
5345
}
5446

@@ -57,33 +49,41 @@ vector<dev::solidity::test::FunctionCall> TestFileParser::parseFunctionCalls()
5749
vector<FunctionCall> calls;
5850
if (!accept(SoltToken::EOS))
5951
{
60-
// TODO: check initial token state
61-
expect(SoltToken::Unknown);
52+
assert(m_scanner.currentToken() == SoltToken::Unknown);
53+
m_scanner.scanNextToken();
54+
6255
while (!accept(SoltToken::EOS))
6356
{
6457
if (!accept(SoltToken::Whitespace))
6558
{
6659
FunctionCall call;
6760

68-
expect(SoltToken::Newline);
69-
call.signature = parseFunctionSignature();
61+
/// If this is not the first call in the test,
62+
/// the last call to parseParameter could have eaten the
63+
/// new line already. This could only be fixed with a one
64+
/// token lookahead that checks parseParameter
65+
/// if the next token is an identifier.
66+
if (calls.empty())
67+
expect(SoltToken::Newline);
68+
else
69+
accept(SoltToken::Newline, true);
7070

71+
call.signature = parseFunctionSignature();
7172
if (accept(SoltToken::Comma, true))
7273
call.value = parseFunctionCallValue();
7374
if (accept(SoltToken::Colon, true))
7475
call.arguments = parseFunctionCallArguments();
7576

76-
call.displayMode = parseNewline();
77+
if (accept(SoltToken::Newline, true))
78+
call.displayMode = FunctionCall::DisplayMode::MultiLine;
79+
7780
call.arguments.comment = parseComment();
7881

7982
if (accept(SoltToken::Newline, true))
8083
call.displayMode = FunctionCall::DisplayMode::MultiLine;
81-
expect(SoltToken::Arrow);
8284

85+
expect(SoltToken::Arrow);
8386
call.expectations = parseFunctionCallExpectations();
84-
85-
if (accept(SoltToken::Newline, false))
86-
call.displayMode = parseNewline();
8787
call.expectations.comment = parseComment();
8888

8989
calls.emplace_back(std::move(call));
@@ -121,12 +121,12 @@ bool TestFileParser::accept(SoltToken _token, bool const _expect)
121121
bool TestFileParser::expect(SoltToken _token, bool const _advance)
122122
{
123123
if (m_scanner.currentToken() != _token)
124-
throw Error
125-
(Error::Type::ParserError,
126-
"Unexpected " + formatToken(m_scanner.currentToken()) + ": \"" +
127-
m_scanner.currentLiteral() + "\". " +
128-
"Expected \"" + formatToken(_token) + "\"."
129-
);
124+
throw Error(
125+
Error::Type::ParserError,
126+
"Unexpected " + formatToken(m_scanner.currentToken()) + ": \"" +
127+
m_scanner.currentLiteral() + "\". " +
128+
"Expected \"" + formatToken(_token) + "\"."
129+
);
130130
if (_advance)
131131
m_scanner.scanNextToken();
132132
return true;
@@ -143,13 +143,13 @@ string TestFileParser::parseFunctionSignature()
143143
while (!accept(SoltToken::RParen))
144144
{
145145
signature += m_scanner.currentLiteral();
146-
expect(SoltToken::UInt);
146+
expect(SoltToken::Identifier);
147147
while (accept(SoltToken::Comma))
148148
{
149149
signature += m_scanner.currentLiteral();
150150
expect(SoltToken::Comma);
151151
signature += m_scanner.currentLiteral();
152-
expect(SoltToken::UInt);
152+
expect(SoltToken::Identifier);
153153
}
154154
}
155155
signature += formatToken(SoltToken::RParen);
@@ -184,15 +184,18 @@ FunctionCallExpectations TestFileParser::parseFunctionCallExpectations()
184184

185185
auto param = parseParameter();
186186
if (param.abiType.type == ABIType::None)
187+
{
188+
expectations.failure = false;
187189
return expectations;
188-
expectations.parameters.emplace_back(param);
190+
}
191+
expectations.result.emplace_back(param);
189192

190193
while (accept(SoltToken::Comma, true))
191-
expectations.parameters.emplace_back(parseParameter());
194+
expectations.result.emplace_back(parseParameter());
192195

193196
/// We have always one virtual parameter in the parameter list.
194197
/// If its type is FAILURE, the expected result is also a REVERT etc.
195-
if (expectations.parameters.at(0).abiType.type != ABIType::Failure)
198+
if (expectations.result.at(0).abiType.type != ABIType::Failure)
196199
expectations.failure = false;
197200
return expectations;
198201
}
@@ -212,8 +215,9 @@ pair<bytes, ABIType> TestFileParser::parseABITypeLiteral()
212215
{
213216
try
214217
{
215-
u256 number;
216-
ABIType abiType;
218+
u256 number{0};
219+
ABIType abiType{ABIType::None, 0};
220+
217221
if (accept(SoltToken::Sub))
218222
{
219223
abiType = ABIType{ABIType::SignedDec, 32};
@@ -227,7 +231,7 @@ pair<bytes, ABIType> TestFileParser::parseABITypeLiteral()
227231
abiType = ABIType{ABIType::UnsignedDec, 32};
228232
number = convertNumber(parseNumber());
229233
}
230-
if (accept(SoltToken::Failure, true))
234+
else if (accept(SoltToken::Failure, true))
231235
{
232236
abiType = ABIType{ABIType::Failure, 0};
233237
return make_pair(bytes{}, abiType);
@@ -241,13 +245,6 @@ pair<bytes, ABIType> TestFileParser::parseABITypeLiteral()
241245
}
242246
}
243247

244-
solidity::test::FunctionCall::DisplayMode TestFileParser::parseNewline()
245-
{
246-
if (accept(SoltToken::Newline, true))
247-
return FunctionCall::DisplayMode::MultiLine;
248-
return FunctionCall::DisplayMode::SingleLine;
249-
}
250-
251248
string TestFileParser::parseComment()
252249
{
253250
string comment = m_scanner.currentLiteral();
@@ -286,7 +283,6 @@ void TestFileParser::Scanner::scanNextToken()
286283
{
287284
auto detectToken = [](std::string const& _literal = "") -> TokenDesc {
288285
if (_literal == "ether") return TokenDesc{SoltToken::Ether, _literal};
289-
if (_literal == "uint256") return TokenDesc{SoltToken::UInt, _literal};
290286
if (_literal == "FAILURE") return TokenDesc{SoltToken::Failure, _literal};
291287
return TokenDesc{SoltToken::Identifier, _literal};
292288
};
@@ -336,9 +332,9 @@ void TestFileParser::Scanner::scanNextToken()
336332
TokenDesc detectedToken = detectToken(scanIdentifierOrKeyword());
337333
token = selectToken(detectedToken.first, detectedToken.second);
338334
}
339-
else if (isDecimalDigit(current()))
335+
else if (isdigit(current()))
340336
token = selectToken(SoltToken::Number, scanNumber());
341-
else if (isWhiteSpace(current()))
337+
else if (isspace(current()))
342338
token = selectToken(SoltToken::Whitespace);
343339
else if (isEndOfLine())
344340
token = selectToken(SoltToken::EOS);
@@ -348,8 +344,6 @@ void TestFileParser::Scanner::scanNextToken()
348344
}
349345
}
350346
while (token.first == SoltToken::Whitespace);
351-
352-
m_nextToken = token;
353347
m_currentToken = token;
354348
}
355349

@@ -382,7 +376,7 @@ string TestFileParser::Scanner::scanNumber()
382376
{
383377
string number;
384378
number += current();
385-
while (isDecimalDigit(peek()))
379+
while (isdigit(peek()))
386380
{
387381
advance();
388382
number += current();

test/libsolidity/util/TestFileParser.h

+20-26
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ namespace test
5959
T(Identifier, "identifier", 0) \
6060
/* type keywords */ \
6161
K(Ether, "ether", 0) \
62-
K(UInt, "uint256", 0) \
6362
/* special keywords */ \
6463
K(Failure, "FAILURE", 0) \
6564

@@ -75,7 +74,9 @@ enum class SoltToken : unsigned int {
7574
* retrieved while parsing a test. This information is used
7675
* for the conversion of human-readable function arguments and
7776
* return values to `bytes` and vice-versa.
78-
* Defaults to an invalid 0-byte representation.
77+
* Defaults to None, a 0-byte representation. 0-bytes
78+
* can also be interpreted as Failure, which means
79+
* either a REVERT or another EVM failure.
7980
*/
8081
struct ABIType
8182
{
@@ -85,11 +86,8 @@ struct ABIType
8586
Failure,
8687
None
8788
};
88-
ABIType(): type(ABIType::None), size(0) { }
89-
ABIType(Type _type, size_t _size): type(_type), size(_size) { }
90-
91-
Type type;
92-
size_t size;
89+
Type type = ABIType::None;
90+
size_t size = 0;
9391
};
9492

9593
/**
@@ -102,17 +100,19 @@ struct FormatInfo
102100
};
103101

104102
/**
105-
* Parameter abstraction used for the encoding and decoding
106-
* function parameter lists and expectation lists.
103+
* Parameter abstraction used for the encoding and decoding of
104+
* function parameter and expectation / return value lists.
107105
* A parameter list is usually a comma-separated list of literals.
108106
* It should not be possible to call create a parameter holding
109107
* an identifier, but if so, the ABI type would be invalid.
110108
*/
111109
struct Parameter
112110
{
113-
/// ABI encoded `bytes` of parsed expectations. This `bytes`
114-
/// is compared to the actual result of a function call
115-
/// and is taken into account while validating it.
111+
/// ABI encoded / decoded `bytes` of values.
112+
/// These `bytes` are used to pass values to function calls
113+
/// and also to store expected return vales. These are
114+
/// compared to the actual result of a function call
115+
/// and used for validating it.
116116
bytes rawBytes;
117117
/// Types that were used to encode `rawBytes`. Expectations
118118
/// are usually comma separated literals. Their type is auto-
@@ -133,21 +133,22 @@ using ParameterList = std::vector<Parameter>;
133133
*/
134134
struct FunctionCallExpectations
135135
{
136-
/// Representation of the comma-separated (or empty) list of expectation parameters given
137-
/// to a function call.
138-
ParameterList parameters;
136+
/// Representation of the comma-separated (or empty) list of expectated result values
137+
/// attached to the function call object. It is checked against the actual result of
138+
/// a function call when used in test framework.
139+
ParameterList result;
139140
/// Expected status of the transaction. It can be either
140141
/// a REVERT or a different EVM failure (e.g. out-of-gas).
141142
bool failure = true;
142143
/// A Comment that can be attached to the expectations,
143144
/// that is retained and can be displayed.
144145
std::string comment;
145-
/// ABI encoded `bytes` of parsed parameters. This `bytes`
146-
/// passed to the function call.
146+
/// ABI encoded `bytes` of parsed expected return values. It is checked
147+
/// against the actual result of a function call when used in test framework.
147148
bytes rawBytes() const
148149
{
149150
bytes raw;
150-
for (auto const& param: parameters)
151+
for (auto const& param: result)
151152
raw += param.rawBytes;
152153
return raw;
153154
}
@@ -168,7 +169,7 @@ struct FunctionCallArgs
168169
/// A Comment that can be attached to the expectations,
169170
/// that is retained and can be displayed.
170171
std::string comment;
171-
/// ABI encoded `bytes` of parsed parameters. This `bytes`
172+
/// ABI encoded `bytes` of parsed parameters. These `bytes`
172173
/// passed to the function call.
173174
bytes rawBytes() const
174175
{
@@ -257,8 +258,6 @@ class TestFileParser
257258
void scanNextToken();
258259

259260
SoltToken currentToken() { return m_currentToken.first; }
260-
SoltToken peekToken() { return m_nextToken.first; }
261-
262261
std::string currentLiteral() { return m_currentToken.second; }
263262

264263
std::string scanComment();
@@ -283,7 +282,6 @@ class TestFileParser
283282
std::string m_currentLiteral;
284283

285284
TokenDesc m_currentToken;
286-
TokenDesc m_nextToken;
287285
};
288286

289287
bool accept(SoltToken _token, bool const _expect = false);
@@ -321,10 +319,6 @@ class TestFileParser
321319
/// if data type is not supported.
322320
std::pair<bytes, ABIType> parseABITypeLiteral();
323321

324-
/// Accepts a newline `//` and returns DisplayMode::MultiLine
325-
/// if found, DisplayMode::SingleLine otherwise.
326-
FunctionCall::DisplayMode parseNewline();
327-
328322
/// Parses a comment
329323
std::string parseComment();
330324

0 commit comments

Comments
 (0)