mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
SemanticTest: Add support for compileToEwasm
.
This commit is contained in:
parent
fb6468d3e4
commit
b19fdf6050
@ -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<bool>{!m_runWithoutYul, m_runWithYul || m_enforceViaYul})
|
||||
for (bool compileToEwasm: compileViaYul && supportsEwasm() ? set<bool>{false, true} : set<bool>{false})
|
||||
{
|
||||
for (bool compileToEwasm: runWithEwasm ? set<bool>{false, true} : set<bool>{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<string, solidity::test::Address> 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<string, solidity::test::Address> 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
|
||||
|
@ -60,10 +60,13 @@ public:
|
||||
bool deploy(std::string const& _contractName, u256 const& _value, bytes const& _arguments, std::map<std::string, solidity::test::Address> 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<TestFunctionCall> m_tests;
|
||||
bool m_runWithYul = false;
|
||||
bool runWithEwasm = false;
|
||||
bool m_runWithoutYul = true;
|
||||
bool m_enforceViaYul = false;
|
||||
bool m_runWithABIEncoderV1Only = false;
|
||||
|
@ -11,6 +11,7 @@ contract B is A {
|
||||
uint public y = f();
|
||||
}
|
||||
// ====
|
||||
// compileToEwasm: also
|
||||
// compileViaYul: true
|
||||
// ----
|
||||
// constructor() ->
|
||||
|
@ -8,6 +8,7 @@ contract B is A {
|
||||
uint public y = f();
|
||||
}
|
||||
// ====
|
||||
// compileToEwasm: also
|
||||
// compileViaYul: true
|
||||
// ----
|
||||
// constructor() ->
|
Loading…
Reference in New Issue
Block a user