diff --git a/test/libsolidity/SemanticTest.cpp b/test/libsolidity/SemanticTest.cpp index 89b9db0d2..0dc648f37 100644 --- a/test/libsolidity/SemanticTest.cpp +++ b/test/libsolidity/SemanticTest.cpp @@ -47,18 +47,18 @@ SemanticTest::SemanticTest(string const& _filename, langutil::EVMVersion _evmVer m_source = m_reader.source(); m_lineOffset = m_reader.lineNumber(); - string choice = m_reader.stringSetting("compileViaYul", "false"); - if (choice == "also") + string compileViaYul = m_reader.stringSetting("compileViaYul", "false"); + if (compileViaYul == "also") { m_runWithYul = true; m_runWithoutYul = true; } - else if (choice == "true") + else if (compileViaYul == "true") { m_runWithYul = true; m_runWithoutYul = false; } - else if (choice == "false") + else if (compileViaYul == "false") { m_runWithYul = false; m_runWithoutYul = true; @@ -66,7 +66,19 @@ SemanticTest::SemanticTest(string const& _filename, langutil::EVMVersion _evmVer m_enforceViaYul = false; } else - BOOST_THROW_EXCEPTION(runtime_error("Invalid compileViaYul value: " + choice + ".")); + BOOST_THROW_EXCEPTION(runtime_error("Invalid compileViaYul value: " + compileViaYul + ".")); + + string compileToEwasm = m_reader.stringSetting("compileToEwasm", "false"); + if (compileToEwasm == "also") + runWithEwasm = true; + else if (compileToEwasm == "false") + runWithEwasm = false; + else + BOOST_THROW_EXCEPTION(runtime_error("Invalid compileToEwasm value: " + compileToEwasm + ".")); + + // run ewasm tests only, if an ewasm evmc vm was defined + if (runWithEwasm && !supportsEwasm()) + runWithEwasm = false; m_runWithABIEncoderV1Only = m_reader.boolSetting("ABIEncoderV1Only", false); if (m_runWithABIEncoderV1Only && solidity::test::CommonOptions::get().useABIEncoderV2) @@ -84,134 +96,14 @@ SemanticTest::SemanticTest(string const& _filename, langutil::EVMVersion _evmVer TestCase::TestResult SemanticTest::run(ostream& _stream, string const& _linePrefix, bool _formatted) { + TestCase::TestResult results = TestResult::Success; for (bool compileViaYul: set{!m_runWithoutYul, m_runWithYul || m_enforceViaYul}) - for (bool compileToEwasm: compileViaYul && supportsEwasm() ? set{false, true} : set{false}) - { + for (bool compileToEwasm: runWithEwasm ? set{false, true} : set{false}) try { - bool success = true; - - m_compileViaYul = compileViaYul; - m_compileToEwasm = compileToEwasm; - m_compileViaYulCanBeSet = false; - - reset(m_compileToEwasm); - - if (compileViaYul) - AnsiColorized(_stream, _formatted, {BOLD, CYAN}) - << _linePrefix << "Running via Yul" << (m_compileToEwasm ? " (ewasm):" : ":") << endl; - - for (auto& test: m_tests) - test.reset(); - - map libraries; - - bool constructed = false; - - for (auto& test: m_tests) - { - if (constructed) - { - soltestAssert(!test.call().isLibrary, "Libraries have to be deployed before any other call."); - soltestAssert( - !test.call().isConstructor, - "Constructor has to be the first function call expect for library deployments."); - } - else if (test.call().isLibrary) - { - soltestAssert( - deploy(test.call().signature, 0, {}, libraries) && m_transactionSuccessful, - "Failed to deploy library " + test.call().signature); - libraries[test.call().signature] = m_contractAddress; - continue; - } - else - { - if (test.call().isConstructor) - deploy("", test.call().value.value, test.call().arguments.rawBytes(), libraries); - else - soltestAssert(deploy("", 0, bytes(), libraries), "Failed to deploy contract."); - constructed = true; - } - - if (test.call().isConstructor) - { - if (m_transactionSuccessful == test.call().expectations.failure) - success = false; - - test.setFailure(!m_transactionSuccessful); - test.setRawBytes(bytes()); - } - else - { - bytes output; - if (test.call().useCallWithoutSignature) - output = callLowLevel(test.call().arguments.rawBytes(), test.call().value.value); - else - { - soltestAssert( - m_allowNonExistingFunctions - || m_compiler.methodIdentifiers(m_compiler.lastContractName()) - .isMember(test.call().signature), - "The function " + test.call().signature + " is not known to the compiler"); - - output = callContractFunctionWithValueNoEncoding( - test.call().signature, test.call().value.value, test.call().arguments.rawBytes()); - } - - if ((m_transactionSuccessful == test.call().expectations.failure) - || (output != test.call().expectations.rawBytes())) - success = false; - - test.setFailure(!m_transactionSuccessful); - test.setRawBytes(std::move(output)); - test.setContractABI(m_compiler.contractABI(m_compiler.lastContractName())); - } - } - - if (success && !m_runWithYul && compileViaYul) - { - m_compileViaYulCanBeSet = true; - AnsiColorized(_stream, _formatted, {BOLD, YELLOW}) - << _linePrefix << endl - << _linePrefix << "Test can pass via Yul and marked with compileViaYul: false." << endl; - return TestResult::Failure; - } - - if (!success && (m_runWithYul || !compileViaYul)) - { - AnsiColorized(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Expected result:" << endl; - for (auto const& test: m_tests) - { - ErrorReporter errorReporter; - _stream << test.format(errorReporter, _linePrefix, false, _formatted) << endl; - _stream << errorReporter.format(_linePrefix, _formatted); - } - _stream << endl; - AnsiColorized(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Obtained result:" << endl; - for (auto const& test: m_tests) - { - ErrorReporter errorReporter; - _stream << test.format(errorReporter, _linePrefix, true, _formatted) << endl; - _stream << errorReporter.format(_linePrefix, _formatted); - } - AnsiColorized(_stream, _formatted, {BOLD, RED}) - << _linePrefix << endl - << _linePrefix << "Attention: Updates on the test will apply the detected format displayed." - << endl; - if (compileViaYul && m_runWithoutYul) - { - _stream << _linePrefix << endl << _linePrefix; - AnsiColorized(_stream, _formatted, {RED_BACKGROUND}) - << "Note that the test passed without Yul."; - _stream << endl; - } - else if (!compileViaYul && m_runWithYul) - AnsiColorized(_stream, _formatted, {BOLD, YELLOW}) - << _linePrefix << endl - << _linePrefix << "Note that the test also has to pass via Yul." << endl; - return TestResult::Failure; - } + TestCase::TestResult result = run(compileViaYul, compileToEwasm, _stream, _linePrefix, _formatted); + if (result != TestResult::Success) + results = result; } catch (WhiskersError const&) { @@ -241,9 +133,133 @@ TestCase::TestResult SemanticTest::run(ostream& _stream, string const& _linePref continue; throw; } + return results; +} + +TestCase::TestResult SemanticTest::run(bool _compileViaYul, bool _compileToEwasm, ostream& _stream, string const& _linePrefix, bool _formatted) +{ + bool success = true; + + m_compileViaYul = _compileViaYul; + m_compileToEwasm = _compileToEwasm; + m_compileViaYulCanBeSet = false; + + reset(m_compileToEwasm); + + if (_compileViaYul) + AnsiColorized(_stream, _formatted, {BOLD, CYAN}) + << _linePrefix << "Running via Yul" << (m_compileToEwasm ? " (ewasm):" : ":") << endl; + + for (auto& test: m_tests) + test.reset(); + + map libraries; + + bool constructed = false; + + for (auto& test: m_tests) + { + if (constructed) + { + soltestAssert(!test.call().isLibrary, "Libraries have to be deployed before any other call."); + soltestAssert( + !test.call().isConstructor, + "Constructor has to be the first function call expect for library deployments."); + } + else if (test.call().isLibrary) + { + soltestAssert( + deploy(test.call().signature, 0, {}, libraries) && m_transactionSuccessful, + "Failed to deploy library " + test.call().signature); + libraries[test.call().signature] = m_contractAddress; + continue; + } + else + { + if (test.call().isConstructor) + deploy("", test.call().value.value, test.call().arguments.rawBytes(), libraries); + else + soltestAssert(deploy("", 0, bytes(), libraries), "Failed to deploy contract."); + constructed = true; } - return TestResult::Success; + if (test.call().isConstructor) + { + if (m_transactionSuccessful == test.call().expectations.failure) + success = false; + + test.setFailure(!m_transactionSuccessful); + test.setRawBytes(bytes()); + } + else + { + bytes output; + if (test.call().useCallWithoutSignature) + output = callLowLevel(test.call().arguments.rawBytes(), test.call().value.value); + else + { + soltestAssert( + m_allowNonExistingFunctions + || m_compiler.methodIdentifiers(m_compiler.lastContractName()).isMember(test.call().signature), + "The function " + test.call().signature + " is not known to the compiler"); + + output = callContractFunctionWithValueNoEncoding( + test.call().signature, test.call().value.value, test.call().arguments.rawBytes()); + } + + if ((m_transactionSuccessful == test.call().expectations.failure) + || (output != test.call().expectations.rawBytes())) + success = false; + + test.setFailure(!m_transactionSuccessful); + test.setRawBytes(std::move(output)); + test.setContractABI(m_compiler.contractABI(m_compiler.lastContractName())); + } + } + + if (success && !m_runWithYul && _compileViaYul) + { + m_compileViaYulCanBeSet = true; + AnsiColorized(_stream, _formatted, {BOLD, YELLOW}) + << _linePrefix << endl + << _linePrefix << "Test can pass via Yul and marked with compileViaYul: false." << endl; + return TestResult::Failure; + } + + if (!success && (m_runWithYul || !_compileViaYul)) + { + AnsiColorized(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Expected result:" << endl; + for (auto const& test: m_tests) + { + ErrorReporter errorReporter; + _stream << test.format(errorReporter, _linePrefix, false, _formatted) << endl; + _stream << errorReporter.format(_linePrefix, _formatted); + } + _stream << endl; + AnsiColorized(_stream, _formatted, {BOLD, CYAN}) << _linePrefix << "Obtained result:" << endl; + for (auto const& test: m_tests) + { + ErrorReporter errorReporter; + _stream << test.format(errorReporter, _linePrefix, true, _formatted) << endl; + _stream << errorReporter.format(_linePrefix, _formatted); + } + AnsiColorized(_stream, _formatted, {BOLD, RED}) + << _linePrefix << endl + << _linePrefix << "Attention: Updates on the test will apply the detected format displayed." << endl; + if (_compileViaYul && m_runWithoutYul) + { + _stream << _linePrefix << endl << _linePrefix; + AnsiColorized(_stream, _formatted, {RED_BACKGROUND}) << "Note that the test passed without Yul."; + _stream << endl; + } + else if (!_compileViaYul && m_runWithYul) + AnsiColorized(_stream, _formatted, {BOLD, YELLOW}) + << _linePrefix << endl + << _linePrefix << "Note that the test also has to pass via Yul." << endl; + return TestResult::Failure; + } + + return success ? TestResult::Success : TestResult::Failure; } void SemanticTest::printSource(ostream& _stream, string const& _linePrefix, bool) const diff --git a/test/libsolidity/SemanticTest.h b/test/libsolidity/SemanticTest.h index 94d14a363..a5e019054 100644 --- a/test/libsolidity/SemanticTest.h +++ b/test/libsolidity/SemanticTest.h @@ -60,10 +60,13 @@ public: bool deploy(std::string const& _contractName, u256 const& _value, bytes const& _arguments, std::map const& _libraries = {}); private: + TestResult run(bool _compileViaYul, bool _compileToEwasm, std::ostream& _stream, std::string const& _linePrefix, bool _formatted); + std::string m_source; std::size_t m_lineOffset; std::vector m_tests; bool m_runWithYul = false; + bool runWithEwasm = false; bool m_runWithoutYul = true; bool m_enforceViaYul = false; bool m_runWithABIEncoderV1Only = false; diff --git a/test/libsolidity/semanticTests/constructor_inheritance_init_order.sol b/test/libsolidity/semanticTests/constructor_inheritance_init_order.sol index 898edf6ad..58b87c0c9 100644 --- a/test/libsolidity/semanticTests/constructor_inheritance_init_order.sol +++ b/test/libsolidity/semanticTests/constructor_inheritance_init_order.sol @@ -11,6 +11,7 @@ contract B is A { uint public y = f(); } // ==== +// compileToEwasm: also // compileViaYul: true // ---- // constructor() -> diff --git a/test/libsolidity/semanticTests/constructor_ihneritance_init_order_2.sol b/test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol similarity index 90% rename from test/libsolidity/semanticTests/constructor_ihneritance_init_order_2.sol rename to test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol index db5f45560..5222e0b2d 100644 --- a/test/libsolidity/semanticTests/constructor_ihneritance_init_order_2.sol +++ b/test/libsolidity/semanticTests/constructor_inheritance_init_order_2.sol @@ -8,6 +8,7 @@ contract B is A { uint public y = f(); } // ==== +// compileToEwasm: also // compileViaYul: true // ---- // constructor() ->