From ba44baa0ebd9011e0190b0353261c3a440bb8ec1 Mon Sep 17 00:00:00 2001 From: Alexander Arlt Date: Thu, 20 May 2021 19:52:56 -0500 Subject: [PATCH] [isoltest] Add bytecode builtin. --- test/ExecutionFramework.h | 7 +++ test/libsolidity/SemanticTest.cpp | 49 ++++++++++++++++++- test/libsolidity/SemanticTest.h | 4 +- .../isoltestTesting/bytecode.sol | 20 ++++++++ 4 files changed, 77 insertions(+), 3 deletions(-) create mode 100644 test/libsolidity/semanticTests/isoltestTesting/bytecode.sol diff --git a/test/ExecutionFramework.h b/test/ExecutionFramework.h index de88679c7..3fba0d5c0 100644 --- a/test/ExecutionFramework.h +++ b/test/ExecutionFramework.h @@ -247,6 +247,13 @@ public: return m_sender; } + bytes returndata() const + { + return m_output; + } + + bool transactionSuccessful() const { return m_transactionSuccessful; } + private: template auto callCppAndEncodeResult(CppFunction const& _cppFunction, Args const&... _arguments) diff --git a/test/libsolidity/SemanticTest.cpp b/test/libsolidity/SemanticTest.cpp index 1af3cac34..305ca40a0 100644 --- a/test/libsolidity/SemanticTest.cpp +++ b/test/libsolidity/SemanticTest.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -175,11 +176,43 @@ map SemanticTest::makeBuiltins() return toBigEndian(h256(ExecutionFramework::setAccount(accountNumber).asBytes(), h256::AlignRight)); } }, + { + "bytecode", + [this](FunctionCall const& _call) -> optional + { + bool result = false; + optional regexPattern; + soltestAssert(m_deployedBytecode.has_value(), "No bytecode deployed."); + soltestAssert(_call.arguments.parameters.size() == 1, "Bytecode pattern string expected."); + string pattern = _call.arguments.parameters.at(0).rawString; + bytes bytecode = m_deployedBytecode.value(); + if (pattern.length() >= 2 && boost::starts_with(pattern, "\"") && boost::ends_with(pattern, "\"")) + { + pattern = pattern.substr(1, pattern.length() - 2); + try + { + regexPattern = regex(pattern); + } + catch (std::regex_error const&) + { + } + } + if (regexPattern.has_value()) + result = regex_match(toHex(bytecode), regexPattern.value()); + else + { + soltestAssert(isValidHex(pattern), "Must be a valid hex string or a regular expression."); + result = toHex(bytecode).find(pattern.substr(2)) != std::string::npos; + } + + return toBigEndian(u256(result ? 1 : 0)); + } + }, }; } -vector SemanticTest::makeSideEffectHooks() const +vector SemanticTest::makeSideEffectHooks() { return { [](FunctionCall const& _call) -> vector @@ -192,7 +225,19 @@ vector SemanticTest::makeSideEffectHooks() const return result; } return {}; - }}; + }, + [this](FunctionCall const& _call) -> vector + { + if (boost::starts_with(_call.signature, "constructor(")) + { + if (ExecutionFramework::transactionSuccessful()) + m_deployedBytecode = ExecutionFramework::returndata(); + else + m_deployedBytecode.reset(); + } + return {}; + }, + }; } TestCase::TestResult SemanticTest::run(ostream& _stream, string const& _linePrefix, bool _formatted) diff --git a/test/libsolidity/SemanticTest.h b/test/libsolidity/SemanticTest.h index 97fdb2de6..8ab8ff5c7 100644 --- a/test/libsolidity/SemanticTest.h +++ b/test/libsolidity/SemanticTest.h @@ -23,6 +23,7 @@ #include #include +#include #include #include #include @@ -81,7 +82,7 @@ private: TestResult runTest(std::ostream& _stream, std::string const& _linePrefix, bool _formatted, bool _isYulRun, bool _isEwasmRun); bool checkGasCostExpectation(TestFunctionCall& io_test, bool _compileViaYul) const; std::map makeBuiltins(); - std::vector makeSideEffectHooks() const; + std::vector makeSideEffectHooks(); SourceMap m_sources; std::size_t m_lineOffset; std::vector m_tests; @@ -99,6 +100,7 @@ private: bool m_gasCostFailure = false; bool m_enforceGasCost = false; u256 m_enforceGasCostMinValue; + std::optional m_deployedBytecode{}; }; } diff --git a/test/libsolidity/semanticTests/isoltestTesting/bytecode.sol b/test/libsolidity/semanticTests/isoltestTesting/bytecode.sol new file mode 100644 index 000000000..9ae7062ad --- /dev/null +++ b/test/libsolidity/semanticTests/isoltestTesting/bytecode.sol @@ -0,0 +1,20 @@ +contract SmokeTest { + constructor() + { + } +} +// ==== +// compileViaYul: also +// ---- +// constructor() +// bytecode: 0x00112233 -> 0 +// bytecode: 0x60806040526 -> 1 +// bytecode: 0x806040526 -> 1 +// bytecode: 0x6040526 -> 1 +// bytecode: 0x5040526 -> 0 +// bytecode: "(60).*" -> 1 +// bytecode: ".*(40).*" -> 1 +// bytecode: ".*40.*6.*" -> 1 +// bytecode: ".*40.*600000.*" -> 0 +// bytecode: ".*40.*600011.*" -> 0 +// bytecode: ".*40.*6000.*" -> 1