1313*/
1414
1515#include < test/libsolidity/SemanticTest.h>
16+
1617#include < libsolutil/Whiskers.h>
1718#include < libyul/Exceptions.h>
1819#include < test/Common.h>
20+ #include < test/libsolidity/util/BytesUtils.h>
21+
1922#include < boost/algorithm/string.hpp>
2023#include < boost/algorithm/string/predicate.hpp>
2124#include < boost/algorithm/string/trim.hpp>
2528#include < cctype>
2629#include < fstream>
2730#include < memory>
31+ #include < optional>
2832#include < stdexcept>
33+ #include < utility>
2934
3035using namespace std ;
3136using namespace solidity ;
@@ -47,6 +52,22 @@ SemanticTest::SemanticTest(string const& _filename, langutil::EVMVersion _evmVer
4752 m_lineOffset(m_reader.lineNumber()),
4853 m_enforceViaYul(enforceViaYul)
4954{
55+ auto simpleSmokeBuiltin = [](FunctionCall const & _call) -> std::optional<bytes> {
56+ // This function is only used in test/libsolidity/semanticTests/builtins/smoke.sol.
57+ // It could be removed when we have actual builtins.
58+ std::optional<bytes> result;
59+ if (_call.arguments .parameters .size () < 3 )
60+ {
61+ result = bytes ();
62+ for (auto const & parameter: _call.arguments .parameters )
63+ result.value () += util::toBigEndian (u256{util::fromHex (parameter.rawString )});
64+ }
65+ return result;
66+ };
67+ m_builtins[" smoke_test0" ] = simpleSmokeBuiltin;
68+ m_builtins[" smoke_test1" ] = simpleSmokeBuiltin;
69+ m_builtins[" smoke_test2" ] = simpleSmokeBuiltin;
70+
5071 string choice = m_reader.stringSetting (" compileViaYul" , " default" );
5172 if (choice == " also" )
5273 {
@@ -119,7 +140,13 @@ TestCase::TestResult SemanticTest::run(ostream& _stream, string const& _linePref
119140 return result;
120141}
121142
122- TestCase::TestResult SemanticTest::runTest (ostream& _stream, string const & _linePrefix, bool _formatted, bool _compileViaYul, bool _compileToEwasm)
143+ TestCase::TestResult SemanticTest::runTest (
144+ ostream& _stream,
145+ string const & _linePrefix,
146+ bool _formatted,
147+ bool _compileViaYul,
148+ bool _compileToEwasm
149+ )
123150{
124151 bool success = true ;
125152
@@ -142,21 +169,25 @@ TestCase::TestResult SemanticTest::runTest(ostream& _stream, string const& _line
142169 if (_compileViaYul)
143170 AnsiColorized (_stream, _formatted, {BOLD, CYAN}) << _linePrefix << " Running via Yul:" << endl;
144171
145- for (auto & test: m_tests)
172+ for (TestFunctionCall & test: m_tests)
146173 test.reset ();
147174
148175 map<string, solidity::test::Address> libraries;
149176
150177 bool constructed = false ;
151178
152- for (auto & test: m_tests)
179+ for (TestFunctionCall & test: m_tests)
153180 {
154181 if (constructed)
155182 {
156- soltestAssert (test.call ().kind != FunctionCall::Kind::Library, " Libraries have to be deployed before any other call." );
183+ soltestAssert (
184+ test.call ().kind != FunctionCall::Kind::Library,
185+ " Libraries have to be deployed before any other call."
186+ );
157187 soltestAssert (
158188 test.call ().kind != FunctionCall::Kind::Constructor,
159- " Constructor has to be the first function call expect for library deployments." );
189+ " Constructor has to be the first function call expect for library deployments."
190+ );
160191 }
161192 else if (test.call ().kind == FunctionCall::Kind::Library)
162193 {
@@ -197,6 +228,17 @@ TestCase::TestResult SemanticTest::runTest(ostream& _stream, string const& _line
197228 bytes output;
198229 if (test.call ().kind == FunctionCall::Kind::LowLevel)
199230 output = callLowLevel (test.call ().arguments .rawBytes (), test.call ().value .value );
231+ else if (test.call ().kind == FunctionCall::Kind::Builtin)
232+ {
233+ std::optional<bytes> builtinOutput = m_builtins.at (test.call ().signature )(test.call ());
234+ if (builtinOutput.has_value ())
235+ {
236+ m_transactionSuccessful = true ;
237+ output = builtinOutput.value ();
238+ }
239+ else
240+ m_transactionSuccessful = false ;
241+ }
200242 else
201243 {
202244 soltestAssert (
@@ -241,15 +283,15 @@ TestCase::TestResult SemanticTest::runTest(ostream& _stream, string const& _line
241283 if (!success && (m_runWithYul || !_compileViaYul))
242284 {
243285 AnsiColorized (_stream, _formatted, {BOLD, CYAN}) << _linePrefix << " Expected result:" << endl;
244- for (auto const & test: m_tests)
286+ for (TestFunctionCall const & test: m_tests)
245287 {
246288 ErrorReporter errorReporter;
247289 _stream << test.format (errorReporter, _linePrefix, false , _formatted) << endl;
248290 _stream << errorReporter.format (_linePrefix, _formatted);
249291 }
250292 _stream << endl;
251293 AnsiColorized (_stream, _formatted, {BOLD, CYAN}) << _linePrefix << " Obtained result:" << endl;
252- for (auto const & test: m_tests)
294+ for (TestFunctionCall const & test: m_tests)
253295 {
254296 ErrorReporter errorReporter;
255297 _stream << test.format (errorReporter, _linePrefix, true , _formatted) << endl;
@@ -320,7 +362,7 @@ void SemanticTest::printSource(ostream& _stream, string const& _linePrefix, bool
320362
321363void SemanticTest::printUpdatedExpectations (ostream& _stream, string const &) const
322364{
323- for (auto const & test: m_tests)
365+ for (TestFunctionCall const & test: m_tests)
324366 _stream << test.format (" " , true , false ) << endl;
325367}
326368
@@ -340,12 +382,16 @@ void SemanticTest::printUpdatedSettings(ostream& _stream, string const& _linePre
340382
341383void SemanticTest::parseExpectations (istream& _stream)
342384{
343- TestFileParser parser{_stream};
344- auto functionCalls = parser.parseFunctionCalls (m_lineOffset);
345- std::move (functionCalls.begin (), functionCalls.end (), back_inserter (m_tests));
385+ TestFileParser parser{_stream, &m_builtins};
386+ m_tests += parser.parseFunctionCalls (m_lineOffset);
346387}
347388
348- bool SemanticTest::deploy (string const & _contractName, u256 const & _value, bytes const & _arguments, map<string, solidity::test::Address> const & _libraries)
389+ bool SemanticTest::deploy (
390+ string const & _contractName,
391+ u256 const & _value,
392+ bytes const & _arguments,
393+ map<string, solidity::test::Address> const & _libraries
394+ )
349395{
350396 auto output = compileAndRunWithoutCheck (m_sources.sources , _value, _contractName, _arguments, _libraries);
351397 return !output.empty () && m_transactionSuccessful;
0 commit comments