diff --git a/test/libsolidity/SemanticTest.cpp b/test/libsolidity/SemanticTest.cpp index f083fae76..35ea80bd9 100644 --- a/test/libsolidity/SemanticTest.cpp +++ b/test/libsolidity/SemanticTest.cpp @@ -80,6 +80,12 @@ SemanticTest::SemanticTest(string const& _filename, langutil::EVMVersion _evmVer m_settings.erase("revertStrings"); } + if (m_settings.count("allowNonExistingFunctions")) + { + m_validatedSettings["allowNonExistingFunctions"] = true; + m_settings.erase("allowNonExistingFunctions"); + } + parseExpectations(file); soltestAssert(!m_tests.empty(), "No tests specified in " + _filename); } @@ -143,13 +149,22 @@ TestCase::TestResult SemanticTest::run(ostream& _stream, string const& _linePref } else { - bytes output = test.call().useCallWithoutSignature ? - callLowLevel(test.call().arguments.rawBytes(), test.call().value) : - callContractFunctionWithValueNoEncoding( + bytes output; + if (test.call().useCallWithoutSignature) + output = callLowLevel(test.call().arguments.rawBytes(), test.call().value); + else + { + soltestAssert( + m_validatedSettings.count("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, test.call().arguments.rawBytes() ); + } if ((m_transactionSuccessful == test.call().expectations.failure) || (output != test.call().expectations.rawBytes())) success = false; diff --git a/test/libsolidity/semanticTests/empty_contract.sol b/test/libsolidity/semanticTests/empty_contract.sol index 8950f01d1..f81e0aa2a 100644 --- a/test/libsolidity/semanticTests/empty_contract.sol +++ b/test/libsolidity/semanticTests/empty_contract.sol @@ -2,5 +2,6 @@ contract test { } // ==== // compileViaYul: also +// allowNonExistingFunctions: true // ---- // i_am_not_there() -> FAILURE diff --git a/test/libsolidity/semanticTests/functionCall/member_accessors.sol b/test/libsolidity/semanticTests/functionCall/member_accessors.sol index 67cb767db..238d99a61 100644 --- a/test/libsolidity/semanticTests/functionCall/member_accessors.sol +++ b/test/libsolidity/semanticTests/functionCall/member_accessors.sol @@ -13,6 +13,7 @@ contract test { uint256 super_secret_data; } // ==== +// allowNonExistingFunctions: true // compileViaYul: also // ---- // data() -> 8 diff --git a/test/libsolidity/semanticTests/functionCall/multiple_functions.sol b/test/libsolidity/semanticTests/functionCall/multiple_functions.sol index 981608d89..3c60a13f1 100644 --- a/test/libsolidity/semanticTests/functionCall/multiple_functions.sol +++ b/test/libsolidity/semanticTests/functionCall/multiple_functions.sol @@ -4,6 +4,8 @@ contract test { function c() public returns(uint n) { return 2; } function f() public returns(uint n) { return 3; } } +// ==== +// allowNonExistingFunctions: true // ---- // a() -> 0 // b() -> 1 diff --git a/test/libsolidity/semanticTests/smoke/failure.sol b/test/libsolidity/semanticTests/smoke/failure.sol index ee1064062..e693a8459 100644 --- a/test/libsolidity/semanticTests/smoke/failure.sol +++ b/test/libsolidity/semanticTests/smoke/failure.sol @@ -14,6 +14,7 @@ contract C { } } // ==== +// allowNonExistingFunctions: true // EVMVersion: >homestead // ---- // _() -> FAILURE diff --git a/test/libsolidity/semanticTests/smoke/multiline.sol b/test/libsolidity/semanticTests/smoke/multiline.sol index 1663a6de4..ff8ee813e 100644 --- a/test/libsolidity/semanticTests/smoke/multiline.sol +++ b/test/libsolidity/semanticTests/smoke/multiline.sol @@ -4,6 +4,7 @@ contract C { } } // ==== +// allowNonExistingFunctions: true // compileViaYul: also // ---- // f(uint256,uint256,uint256,uint256,uint256): 1, 1, 1, 1, 1 diff --git a/test/libsolidity/semanticTests/viaYul/smoke_test.sol b/test/libsolidity/semanticTests/viaYul/smoke_test.sol index 0e0a7d4d5..d5c025734 100644 --- a/test/libsolidity/semanticTests/viaYul/smoke_test.sol +++ b/test/libsolidity/semanticTests/viaYul/smoke_test.sol @@ -1,6 +1,7 @@ contract C { } // ==== +// allowNonExistingFunctions: true // compileViaYul: true // ---- // f() -> FAILURE diff --git a/test/libsolidity/util/TestFunctionCall.cpp b/test/libsolidity/util/TestFunctionCall.cpp index ac7a92a08..22dc82aa8 100644 --- a/test/libsolidity/util/TestFunctionCall.cpp +++ b/test/libsolidity/util/TestFunctionCall.cpp @@ -114,6 +114,9 @@ string TestFunctionCall::format( } else { + if (m_calledNonExistingFunction) + _errorReporter.warning("The function \"" + m_call.signature + "\" is not known to the compiler."); + bytes output = m_rawBytes; bool const isFailure = m_failure; result = isFailure ? @@ -300,6 +303,7 @@ void TestFunctionCall::reset() { m_rawBytes = bytes{}; m_failure = true; + m_calledNonExistingFunction = false; } bool TestFunctionCall::matchesExpectation() const diff --git a/test/libsolidity/util/TestFunctionCall.h b/test/libsolidity/util/TestFunctionCall.h index baa0990b1..6f21fc9eb 100644 --- a/test/libsolidity/util/TestFunctionCall.h +++ b/test/libsolidity/util/TestFunctionCall.h @@ -77,6 +77,7 @@ public: void reset(); FunctionCall const& call() const { return m_call; } + void calledNonExistingFunction() { m_calledNonExistingFunction = true; } void setFailure(const bool _failure) { m_failure = _failure; } void setRawBytes(const bytes _rawBytes) { m_rawBytes = _rawBytes; } void setContractABI(Json::Value _contractABI) { m_contractABI = std::move(_contractABI); } @@ -129,6 +130,8 @@ private: /// JSON object which holds the contract ABI and that is used to set the output formatting /// in the interactive update routine. Json::Value m_contractABI; + /// Flags that the test failed because the called function is not known to exist on the contract. + bool m_calledNonExistingFunction = false; }; }