mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Empty storage option for isoltest.
This commit is contained in:
parent
f42280f5c9
commit
3b8c038647
@ -176,7 +176,16 @@ TestCase::TestResult SemanticTest::runTest(ostream& _stream, string const& _line
|
|||||||
constructed = true;
|
constructed = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (test.call().kind == FunctionCall::Kind::Constructor)
|
if (test.call().kind == FunctionCall::Kind::Storage)
|
||||||
|
{
|
||||||
|
test.setFailure(false);
|
||||||
|
bytes result(1, !storageEmpty(m_contractAddress));
|
||||||
|
test.setRawBytes(result);
|
||||||
|
soltestAssert(test.call().expectations.rawBytes().size() == 1, "");
|
||||||
|
if (test.call().expectations.rawBytes() != result)
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
else if (test.call().kind == FunctionCall::Kind::Constructor)
|
||||||
{
|
{
|
||||||
if (m_transactionSuccessful == test.call().expectations.failure)
|
if (m_transactionSuccessful == test.call().expectations.failure)
|
||||||
success = false;
|
success = false;
|
||||||
|
@ -41,6 +41,10 @@ contract c {
|
|||||||
// ====
|
// ====
|
||||||
// compileViaYul: also
|
// compileViaYul: also
|
||||||
// ----
|
// ----
|
||||||
|
// storage: empty
|
||||||
// test_short() -> 1780731860627700044960722568376587075150542249149356309979516913770823710
|
// test_short() -> 1780731860627700044960722568376587075150542249149356309979516913770823710
|
||||||
|
// storage: nonempty
|
||||||
// test_long() -> 67
|
// test_long() -> 67
|
||||||
|
// storage: nonempty
|
||||||
// test_pop() -> 1780731860627700044960722568376592200742329637303199754547598369979433020
|
// test_pop() -> 1780731860627700044960722568376592200742329637303199754547598369979433020
|
||||||
|
// storage: nonempty
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
contract Test {
|
||||||
|
bytes x;
|
||||||
|
function set(bytes memory _a) public { x = _a; }
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// set(bytes): 0x20, 3, "abc"
|
||||||
|
// storage: nonempty
|
||||||
|
// set(bytes): 0x20, 0
|
||||||
|
// storage: empty
|
||||||
|
// set(bytes): 0x20, 31, "1234567890123456789012345678901"
|
||||||
|
// storage: nonempty
|
||||||
|
// set(bytes): 0x20, 36, "12345678901234567890123456789012", "XXXX"
|
||||||
|
// storage: nonempty
|
||||||
|
// set(bytes): 0x20, 3, "abc"
|
||||||
|
// storage: nonempty
|
||||||
|
// set(bytes): 0x20, 0
|
||||||
|
// storage: empty
|
||||||
|
// set(bytes): 0x20, 3, "abc"
|
||||||
|
// storage: nonempty
|
||||||
|
// set(bytes): 0x20, 36, "12345678901234567890123456789012", "XXXX"
|
||||||
|
// storage: nonempty
|
||||||
|
// set(bytes): 0x20, 0
|
||||||
|
// storage: empty
|
||||||
|
// set(bytes): 0x20, 66, "12345678901234567890123456789012", "12345678901234567890123456789012", "12"
|
||||||
|
// storage: nonempty
|
||||||
|
// set(bytes): 0x20, 3, "abc"
|
||||||
|
// storage: nonempty
|
||||||
|
// set(bytes): 0x20, 0
|
||||||
|
// storage: empty
|
@ -58,6 +58,7 @@ namespace solidity::frontend::test
|
|||||||
K(Library, "library", 0) \
|
K(Library, "library", 0) \
|
||||||
K(Right, "right", 0) \
|
K(Right, "right", 0) \
|
||||||
K(Failure, "FAILURE", 0) \
|
K(Failure, "FAILURE", 0) \
|
||||||
|
K(Storage, "storage", 0) \
|
||||||
|
|
||||||
namespace soltest
|
namespace soltest
|
||||||
{
|
{
|
||||||
@ -284,7 +285,9 @@ struct FunctionCall
|
|||||||
/// a low-level call with unstructured calldata will be issued.
|
/// a low-level call with unstructured calldata will be issued.
|
||||||
LowLevel,
|
LowLevel,
|
||||||
/// Marks a library deployment call.
|
/// 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;
|
Kind kind = Kind::Regular;
|
||||||
/// Marks this function call as "short-handed", meaning
|
/// Marks this function call as "short-handed", meaning
|
||||||
|
@ -85,6 +85,21 @@ vector<solidity::frontend::test::FunctionCall> TestFileParser::parseFunctionCall
|
|||||||
call.kind = FunctionCall::Kind::Library;
|
call.kind = FunctionCall::Kind::Library;
|
||||||
call.expectations.failure = false;
|
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
|
else
|
||||||
{
|
{
|
||||||
bool lowLevelCall = false;
|
bool lowLevelCall = false;
|
||||||
@ -484,6 +499,7 @@ void TestFileParser::Scanner::scanNextToken()
|
|||||||
if (_literal == "right") return TokenDesc{Token::Right, _literal};
|
if (_literal == "right") return TokenDesc{Token::Right, _literal};
|
||||||
if (_literal == "hex") return TokenDesc{Token::Hex, _literal};
|
if (_literal == "hex") return TokenDesc{Token::Hex, _literal};
|
||||||
if (_literal == "FAILURE") return TokenDesc{Token::Failure, _literal};
|
if (_literal == "FAILURE") return TokenDesc{Token::Failure, _literal};
|
||||||
|
if (_literal == "storage") return TokenDesc{Token::Storage, _literal};
|
||||||
return TokenDesc{Token::Identifier, _literal};
|
return TokenDesc{Token::Identifier, _literal};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -44,7 +44,8 @@ namespace solidity::frontend::test
|
|||||||
* // h(uint256), 1 ether: 42
|
* // h(uint256), 1 ether: 42
|
||||||
* // -> FAILURE # If REVERT or other EVM failure was detected #
|
* // -> FAILURE # If REVERT or other EVM failure was detected #
|
||||||
* // () # Call fallback function #
|
* // () # Call fallback function #
|
||||||
* // (), 1 ether # Call ether function #
|
* // (), 1 ether # Call receive ether function #
|
||||||
|
* // EMPTY_STORAGE # Check that storage is empty
|
||||||
* ...
|
* ...
|
||||||
*/
|
*/
|
||||||
class TestFileParser
|
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()
|
BOOST_AUTO_TEST_SUITE_END()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -61,6 +61,20 @@ string TestFunctionCall::format(
|
|||||||
stream << _linePrefix << newline << ws << "library:" << ws << m_call.signature;
|
stream << _linePrefix << newline << ws << "library:" << ws << m_call.signature;
|
||||||
return;
|
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.
|
/// Formats the function signature. This is the same independent from the display-mode.
|
||||||
stream << _linePrefix << newline << ws << m_call.signature;
|
stream << _linePrefix << newline << ws << m_call.signature;
|
||||||
|
Loading…
Reference in New Issue
Block a user