Empty storage option for isoltest.

This commit is contained in:
chriseth
2020-10-29 13:55:07 +01:00
parent f42280f5c9
commit 3b8c038647
8 changed files with 101 additions and 3 deletions
+4 -1
View File
@@ -58,6 +58,7 @@ namespace solidity::frontend::test
K(Library, "library", 0) \
K(Right, "right", 0) \
K(Failure, "FAILURE", 0) \
K(Storage, "storage", 0) \
namespace soltest
{
@@ -284,7 +285,9 @@ struct FunctionCall
/// a low-level call with unstructured calldata will be issued.
LowLevel,
/// Marks a library deployment call.
Library
Library,
/// Check that the storage of the current contract is empty or non-empty.
Storage
};
Kind kind = Kind::Regular;
/// Marks this function call as "short-handed", meaning
+16
View File
@@ -85,6 +85,21 @@ vector<solidity::frontend::test::FunctionCall> TestFileParser::parseFunctionCall
call.kind = FunctionCall::Kind::Library;
call.expectations.failure = false;
}
else if (accept(Token::Storage, true))
{
expect(Token::Colon);
call.expectations.failure = false;
call.expectations.result.push_back(Parameter());
// empty / non-empty is encoded as false / true
if (m_scanner.currentLiteral() == "empty")
call.expectations.result.back().rawBytes = bytes(1, uint8_t(false));
else if (m_scanner.currentLiteral() == "nonempty")
call.expectations.result.back().rawBytes = bytes(1, uint8_t(true));
else
throw TestParserError("Expected \"empty\" or \"nonempty\".");
call.kind = FunctionCall::Kind::Storage;
m_scanner.scanNextToken();
}
else
{
bool lowLevelCall = false;
@@ -484,6 +499,7 @@ void TestFileParser::Scanner::scanNextToken()
if (_literal == "right") return TokenDesc{Token::Right, _literal};
if (_literal == "hex") return TokenDesc{Token::Hex, _literal};
if (_literal == "FAILURE") return TokenDesc{Token::Failure, _literal};
if (_literal == "storage") return TokenDesc{Token::Storage, _literal};
return TokenDesc{Token::Identifier, _literal};
};
+2 -1
View File
@@ -44,7 +44,8 @@ namespace solidity::frontend::test
* // h(uint256), 1 ether: 42
* // -> FAILURE # If REVERT or other EVM failure was detected #
* // () # Call fallback function #
* // (), 1 ether # Call ether function #
* // (), 1 ether # Call receive ether function #
* // EMPTY_STORAGE # Check that storage is empty
* ...
*/
class TestFileParser
@@ -953,6 +953,28 @@ BOOST_AUTO_TEST_CASE(library)
);
}
BOOST_AUTO_TEST_CASE(empty_storage)
{
char const* source = R"(
// storage: empty
)";
auto const calls = parse(source);
BOOST_REQUIRE_EQUAL(calls.size(), 1);
BOOST_CHECK(calls.at(0).kind == FunctionCall::Kind::Storage);
BOOST_CHECK(calls.at(0).expectations.result.front().rawBytes == bytes(1, 0));
}
BOOST_AUTO_TEST_CASE(nonempty_storage)
{
char const* source = R"(
// storage: nonempty
)";
auto const calls = parse(source);
BOOST_REQUIRE_EQUAL(calls.size(), 1);
BOOST_CHECK(calls.at(0).kind == FunctionCall::Kind::Storage);
BOOST_CHECK(calls.at(0).expectations.result.front().rawBytes == bytes(1, 1));
}
BOOST_AUTO_TEST_SUITE_END()
}
@@ -61,6 +61,20 @@ string TestFunctionCall::format(
stream << _linePrefix << newline << ws << "library:" << ws << m_call.signature;
return;
}
else if (m_call.kind == FunctionCall::Kind::Storage)
{
stream << _linePrefix << newline << ws << "storage" << colon << ws;
soltestAssert(m_rawBytes.size() == 1, "");
soltestAssert(m_call.expectations.rawBytes().size() == 1, "");
bool isEmpty = _renderResult ? m_rawBytes.front() == 0 : m_call.expectations.rawBytes().front() == 0;
string output = isEmpty ? "empty" : "nonempty";
if (_renderResult && !matchesExpectation())
AnsiColorized(stream, highlight, {util::formatting::RED_BACKGROUND}) << output;
else
stream << output;
return;
}
/// Formats the function signature. This is the same independent from the display-mode.
stream << _linePrefix << newline << ws << m_call.signature;