Skip to content

Commit a1c6550

Browse files
committed
[isoltest] Add support for effects.
1 parent 767514e commit a1c6550

File tree

8 files changed

+92
-10
lines changed

8 files changed

+92
-10
lines changed

test/libsolidity/SemanticTest.cpp

+20-3
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,12 @@ SemanticTest::SemanticTest(string const& _filename, langutil::EVMVersion _evmVer
6868
m_builtins["smoke_test1"] = simpleSmokeBuiltin;
6969
m_builtins["smoke_test2"] = simpleSmokeBuiltin;
7070

71+
m_hooks.emplace_back([](FunctionCall const& _call) -> std::vector<std::string> {
72+
if (_call.signature.find("smoke_") != string::npos)
73+
return {_call.signature};
74+
return {};
75+
});
76+
7177
string choice = m_reader.stringSetting("compileViaYul", "default");
7278
if (choice == "also")
7379
{
@@ -140,6 +146,15 @@ TestCase::TestResult SemanticTest::run(ostream& _stream, string const& _linePref
140146
return result;
141147
}
142148

149+
vector<string> SemanticTest::effectsOfCall(FunctionCall const& _call) const
150+
{
151+
vector<string> effects;
152+
for (auto const& hook: m_hooks)
153+
for (auto const& effect: hook(_call))
154+
effects.emplace_back(effect);
155+
return effects;
156+
}
157+
143158
TestCase::TestResult SemanticTest::runTest(
144159
ostream& _stream,
145160
string const& _linePrefix,
@@ -266,6 +281,8 @@ TestCase::TestResult SemanticTest::runTest(
266281
test.setRawBytes(std::move(output));
267282
test.setContractABI(m_compiler.contractABI(m_compiler.lastContractName()));
268283
}
284+
285+
success &= test.call().effects == effectsOfCall(test.call());
269286
}
270287

271288
if (!m_runWithYul && _compileViaYul)
@@ -286,15 +303,15 @@ TestCase::TestResult SemanticTest::runTest(
286303
for (TestFunctionCall const& test: m_tests)
287304
{
288305
ErrorReporter errorReporter;
289-
_stream << test.format(errorReporter, _linePrefix, false, _formatted) << endl;
306+
_stream << test.format(errorReporter, _linePrefix, false, _formatted, effectsOfCall(test.call())) << endl;
290307
_stream << errorReporter.format(_linePrefix, _formatted);
291308
}
292309
_stream << endl;
293310
AnsiColorized(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Obtained result:" << endl;
294311
for (TestFunctionCall const& test: m_tests)
295312
{
296313
ErrorReporter errorReporter;
297-
_stream << test.format(errorReporter, _linePrefix, true, _formatted) << endl;
314+
_stream << test.format(errorReporter, _linePrefix, true, _formatted, effectsOfCall(test.call())) << endl;
298315
_stream << errorReporter.format(_linePrefix, _formatted);
299316
}
300317
AnsiColorized(_stream, _formatted, {BOLD, RED})
@@ -363,7 +380,7 @@ void SemanticTest::printSource(ostream& _stream, string const& _linePrefix, bool
363380
void SemanticTest::printUpdatedExpectations(ostream& _stream, string const&) const
364381
{
365382
for (TestFunctionCall const& test: m_tests)
366-
_stream << test.format("", true, false) << endl;
383+
_stream << test.format("", true, false, effectsOfCall(test.call())) << endl;
367384
}
368385

369386
void SemanticTest::printUpdatedSettings(ostream& _stream, string const& _linePrefix)

test/libsolidity/SemanticTest.h

+3
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@ class SemanticTest: public SolidityExecutionFramework, public EVMVersionRestrict
5959
/// Returns true if deployment was successful, false otherwise.
6060
bool deploy(std::string const& _contractName, u256 const& _value, bytes const& _arguments, std::map<std::string, solidity::test::Address> const& _libraries = {});
6161

62+
std::vector<std::string> effectsOfCall(FunctionCall const& _call) const;
63+
6264
private:
6365
TestResult runTest(std::ostream& _stream, std::string const& _linePrefix, bool _formatted, bool _compileViaYul, bool _compileToEwasm);
6466
SourceMap m_sources;
@@ -72,6 +74,7 @@ class SemanticTest: public SolidityExecutionFramework, public EVMVersionRestrict
7274
bool m_allowNonExistingFunctions = false;
7375
bool m_compileViaYulCanBeSet = false;
7476
std::map<std::string, Builtin> m_builtins{};
77+
std::vector<Hook> m_hooks{};
7578
};
7679

7780
}

test/libsolidity/semanticTests/builtins/smoke.sol

+5
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,12 @@ contract ClientReceipt {
44
// compileViaYul: also
55
// ----
66
// smoke_test0 ->
7+
// - smoke_test0
78
// smoke_test1: 1 -> 1
9+
// - smoke_test1
810
// smoke_test2: 2, 3 -> 2, 3
11+
// - smoke_test2
912
// smoke_test2: 2, 3, 4 -> FAILURE
13+
// - smoke_test2
1014
// smoke_test0 ->
15+
// - smoke_test0

test/libsolidity/util/SoltestTypes.h

+5-1
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ namespace solidity::frontend::test
4242
T(Comma, ",", 0) \
4343
T(Period, ".", 0) \
4444
T(Arrow, "->", 0) \
45+
T(Effect, "- ", 0) \
4546
T(Newline, "//", 0) \
4647
/* Literals & identifier */ \
4748
T(Comment, "#", 0) \
@@ -59,7 +60,7 @@ namespace solidity::frontend::test
5960
K(Library, "library", 0) \
6061
K(Right, "right", 0) \
6162
K(Failure, "FAILURE", 0) \
62-
K(Storage, "storage", 0) \
63+
K(Storage, "storage", 0) \
6364

6465
namespace soltest
6566
{
@@ -299,8 +300,11 @@ struct FunctionCall
299300
/// Marks this function call as "short-handed", meaning
300301
/// no `->` declared.
301302
bool omitsArrow = true;
303+
/// A textual representation of the effect of the function call.
304+
std::vector<std::string> effects{};
302305
};
303306

304307
using Builtin = std::function<std::optional<bytes>(FunctionCall const&)>;
308+
using Hook = std::function<std::vector<std::string>(FunctionCall const&)>;
305309

306310
}

test/libsolidity/util/TestFileParser.cpp

+37-1
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,8 @@ vector<solidity::frontend::test::FunctionCall> TestFileParser::parseFunctionCall
149149
call.kind = FunctionCall::Kind::Constructor;
150150
}
151151

152+
call.effects = parseFunctionCallEffects();
153+
152154
calls.emplace_back(std::move(call));
153155
}
154156
catch (TestParserError const& _e)
@@ -284,6 +286,25 @@ FunctionCallExpectations TestFileParser::parseFunctionCallExpectations()
284286
return expectations;
285287
}
286288

289+
vector<string> TestFileParser::parseFunctionCallEffects()
290+
{
291+
vector<string> result;
292+
while (accept(Token::Effect, false))
293+
{
294+
string effect = m_scanner.currentLiteral();
295+
result.emplace_back(effect);
296+
297+
if (m_scanner.currentToken() == Token::Effect)
298+
m_scanner.scanNextToken();
299+
if (m_scanner.currentToken() == Token::Newline)
300+
m_scanner.scanNextToken();
301+
if (m_scanner.currentToken() == Token::EOS)
302+
break;
303+
}
304+
305+
return result;
306+
}
307+
287308
Parameter TestFileParser::parseParameter()
288309
{
289310
Parameter parameter;
@@ -535,6 +556,11 @@ void TestFileParser::Scanner::scanNextToken()
535556
advance();
536557
selectToken(Token::Arrow);
537558
}
559+
else if (peek() == ' ')
560+
{
561+
advance();
562+
selectToken(Token::Effect, scanEffectString());
563+
}
538564
else
539565
selectToken(Token::Sub);
540566
break;
@@ -590,8 +616,18 @@ void TestFileParser::Scanner::scanNextToken()
590616
BOOST_THROW_EXCEPTION(TestParserError("Unexpected character: '" + string{current()} + "'"));
591617
break;
592618
}
619+
} while (m_currentToken == Token::Whitespace);
620+
}
621+
622+
string TestFileParser::Scanner::scanEffectString()
623+
{
624+
string effect;
625+
while (peek() != '/' && peek() != '\0')
626+
{
627+
advance();
628+
effect += current();
593629
}
594-
while (m_currentToken == Token::Whitespace);
630+
return effect;
595631
}
596632

597633
string TestFileParser::Scanner::scanComment()

test/libsolidity/util/TestFileParser.h

+4
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ class TestFileParser
8383
std::string currentLiteral() { return m_currentLiteral; }
8484

8585
std::string scanComment();
86+
std::string scanEffectString();
8687
std::string scanIdentifierOrKeyword();
8788
std::string scanDecimalNumber();
8889
std::string scanHexNumber();
@@ -141,6 +142,9 @@ class TestFileParser
141142
/// Parses the expected result of a function call execution.
142143
FunctionCallExpectations parseFunctionCallExpectations();
143144

145+
/// Parses the expected effects of a function call execution.
146+
std::vector<std::string> parseFunctionCallEffects();
147+
144148
/// Parses the next parameter in a comma separated list.
145149
/// Takes a newly parsed, and type-annotated `bytes` argument,
146150
/// appends it to the internal `bytes` buffer of the parameter. It can also

test/libsolidity/util/TestFunctionCall.cpp

+13-2
Original file line numberDiff line numberDiff line change
@@ -36,8 +36,8 @@ string TestFunctionCall::format(
3636
ErrorReporter& _errorReporter,
3737
string const& _linePrefix,
3838
bool const _renderResult,
39-
bool const _highlight
40-
) const
39+
bool const _highlight,
40+
std::vector<std::string> _effects) const
4141
{
4242
stringstream stream;
4343

@@ -204,6 +204,17 @@ string TestFunctionCall::format(
204204
stream << comment << m_call.expectations.comment << comment;
205205
}
206206
}
207+
208+
if (!_effects.empty())
209+
{
210+
stream << std::endl;
211+
for (string const& effect: _effects)
212+
{
213+
stream << _linePrefix << "// - " << effect;
214+
if (effect != *_effects.rbegin())
215+
stream << std::endl;
216+
}
217+
}
207218
};
208219

209220
formatOutput(m_call.displayMode == FunctionCall::DisplayMode::SingleLine);

test/libsolidity/util/TestFunctionCall.h

+5-3
Original file line numberDiff line numberDiff line change
@@ -56,19 +56,21 @@ class TestFunctionCall
5656
ErrorReporter& _errorReporter,
5757
std::string const& _linePrefix = "",
5858
bool const _renderResult = false,
59-
bool const _highlight = false
59+
bool const _highlight = false,
60+
std::vector<std::string> _effects = {}
6061
) const;
6162

6263
/// Overloaded version that passes an error reporter which is never used outside
6364
/// of this function.
6465
std::string format(
6566
std::string const& _linePrefix = "",
6667
bool const _renderResult = false,
67-
bool const _highlight = false
68+
bool const _highlight = false,
69+
std::vector<std::string> _effects = {}
6870
) const
6971
{
7072
ErrorReporter reporter;
71-
return format(reporter, _linePrefix, _renderResult, _highlight);
73+
return format(reporter, _linePrefix, _renderResult, _highlight, _effects);
7274
}
7375

7476
/// Resets current results in case the function was called and the result

0 commit comments

Comments
 (0)