mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
[isoltest] Replace storage command with 'storage_empty' builtin.
This commit is contained in:
parent
ca267e50d3
commit
ae09ac018a
@ -31,6 +31,7 @@
|
||||
#include <optional>
|
||||
#include <stdexcept>
|
||||
#include <utility>
|
||||
#include <functional>
|
||||
|
||||
using namespace std;
|
||||
using namespace solidity;
|
||||
@ -52,6 +53,8 @@ SemanticTest::SemanticTest(string const& _filename, langutil::EVMVersion _evmVer
|
||||
m_lineOffset(m_reader.lineNumber()),
|
||||
m_enforceViaYul(enforceViaYul)
|
||||
{
|
||||
initializeBuiltins();
|
||||
|
||||
string choice = m_reader.stringSetting("compileViaYul", "default");
|
||||
if (choice == "also")
|
||||
{
|
||||
@ -107,6 +110,15 @@ SemanticTest::SemanticTest(string const& _filename, langutil::EVMVersion _evmVer
|
||||
soltestAssert(!m_tests.empty(), "No tests specified in " + _filename);
|
||||
}
|
||||
|
||||
void SemanticTest::initializeBuiltins()
|
||||
{
|
||||
m_builtins["storage_empty"] = [this](FunctionCall const& _call) -> std::optional<bytes>
|
||||
{
|
||||
soltestAssert(_call.arguments.parameters.empty(), "No arguments expected.");
|
||||
return toBigEndian(u256(storageEmpty(m_contractAddress) ? 1 : 0));
|
||||
};
|
||||
}
|
||||
|
||||
TestCase::TestResult SemanticTest::run(ostream& _stream, string const& _linePrefix, bool _formatted)
|
||||
{
|
||||
TestResult result = TestResult::Success;
|
||||
@ -190,16 +202,7 @@ TestCase::TestResult SemanticTest::runTest(
|
||||
constructed = true;
|
||||
}
|
||||
|
||||
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 (test.call().kind == FunctionCall::Kind::Constructor)
|
||||
{
|
||||
if (m_transactionSuccessful == test.call().expectations.failure)
|
||||
success = false;
|
||||
|
||||
@ -61,6 +61,9 @@ public:
|
||||
|
||||
private:
|
||||
TestResult runTest(std::ostream& _stream, std::string const& _linePrefix, bool _formatted, bool _compileViaYul, bool _compileToEwasm);
|
||||
|
||||
void initializeBuiltins();
|
||||
|
||||
SourceMap m_sources;
|
||||
std::size_t m_lineOffset;
|
||||
std::vector<TestFunctionCall> m_tests;
|
||||
|
||||
@ -41,10 +41,10 @@ contract c {
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
// test_short() -> 1780731860627700044960722568376587075150542249149356309979516913770823710
|
||||
// storage: nonempty
|
||||
// storage_empty -> false
|
||||
// test_long() -> 67
|
||||
// storage: nonempty
|
||||
// storage_empty -> false
|
||||
// test_pop() -> 1780731860627700044960722568376592200742329637303199754547598369979433020
|
||||
// storage: nonempty
|
||||
// storage_empty -> false
|
||||
|
||||
@ -37,6 +37,6 @@ contract c {
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() -> 0x02000202
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
// clear() -> 0, 0
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
|
||||
@ -21,4 +21,4 @@ contract c {
|
||||
// setData1(uint256,uint256,uint256): 0, 0, 0 ->
|
||||
// copyStorageStorage() ->
|
||||
// getData2(uint256): 0 -> 0, 0
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
|
||||
@ -19,4 +19,4 @@ contract c {
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() -> 4, 5
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
|
||||
@ -8,10 +8,10 @@ contract c {
|
||||
// ----
|
||||
// set(uint256): 1, 2 -> true
|
||||
// set(uint256): 2, 2, 3, 4, 5 -> true
|
||||
// storage: nonempty
|
||||
// storage_empty -> false
|
||||
// copy(uint256,uint256): 1, 2 -> true
|
||||
// storage: nonempty
|
||||
// storage_empty -> false
|
||||
// copy(uint256,uint256): 99, 1 -> true
|
||||
// storage: nonempty
|
||||
// storage_empty -> false
|
||||
// copy(uint256,uint256): 99, 2 -> true
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
|
||||
@ -39,4 +39,4 @@ contract C {
|
||||
// f() -> 0x40, 0x80, 6, 0x6162636465660000000000000000000000000000000000000000000000000000, 0x49, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738390000000000000000000000000000000000000000000000
|
||||
// g() -> 0x40, 0xc0, 0x49, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738390000000000000000000000000000000000000000000000, 0x11, 0x3132333435363738393233343536373839000000000000000000000000000000
|
||||
// h() -> 0x40, 0x60, 0x00, 0x00
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
|
||||
@ -9,6 +9,6 @@ contract c {
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// set(): 1, 2, 3, 4, 5 -> true
|
||||
// storage: nonempty
|
||||
// storage_empty -> false
|
||||
// reset() -> true
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
|
||||
@ -7,6 +7,6 @@ contract c {
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// (): 7 ->
|
||||
// storage: nonempty
|
||||
// storage_empty -> false
|
||||
// del(): 7 -> true
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
|
||||
@ -14,10 +14,10 @@ contract c {
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
// fill() ->
|
||||
// storage: nonempty
|
||||
// storage_empty -> false
|
||||
// halfClear() ->
|
||||
// storage: nonempty
|
||||
// storage_empty -> false
|
||||
// fullClear() ->
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
|
||||
@ -16,8 +16,8 @@ contract c {
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
// fill() -> 8
|
||||
// storage: nonempty
|
||||
// storage_empty -> false
|
||||
// clear() ->
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
|
||||
@ -11,8 +11,8 @@ contract c {
|
||||
// compileViaYul: also
|
||||
// compileToEwasm: also
|
||||
// ----
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
// fill() ->
|
||||
// storage: nonempty
|
||||
// storage_empty -> false
|
||||
// clear() ->
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
|
||||
@ -25,4 +25,4 @@ contract c {
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() -> 1, 2, 3
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
|
||||
@ -9,4 +9,4 @@ contract c {
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() ->
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
|
||||
@ -20,4 +20,4 @@ contract c {
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() -> 38, 28, 18
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
|
||||
@ -20,4 +20,4 @@ contract c {
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() -> 20, 10
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
|
||||
@ -18,4 +18,4 @@ contract c {
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() -> true
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
|
||||
@ -17,4 +17,4 @@ contract c {
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// test() ->
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
|
||||
@ -14,4 +14,4 @@ contract c {
|
||||
// compileToEwasm: also
|
||||
// ----
|
||||
// test() ->
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
|
||||
@ -11,8 +11,8 @@ contract c {
|
||||
// compileViaYul: also
|
||||
// compileToEwasm: also
|
||||
// ----
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
// fill() ->
|
||||
// storage: nonempty
|
||||
// storage_empty -> false
|
||||
// clear() ->
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
|
||||
@ -0,0 +1,6 @@
|
||||
contract StorageEmpty {
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// storage_empty -> true
|
||||
@ -0,0 +1,10 @@
|
||||
contract StorageNotEmpty {
|
||||
uint256 x;
|
||||
function set(uint256 _a) public { x = _a; }
|
||||
}
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// storage_empty -> true
|
||||
// set(uint256): 1 ->
|
||||
// storage_empty -> false
|
||||
@ -6,26 +6,26 @@ contract Test {
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// set(bytes): 0x20, 3, "abc"
|
||||
// storage: nonempty
|
||||
// storage_empty -> false
|
||||
// set(bytes): 0x20, 0
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
// set(bytes): 0x20, 31, "1234567890123456789012345678901"
|
||||
// storage: nonempty
|
||||
// storage_empty -> false
|
||||
// set(bytes): 0x20, 36, "12345678901234567890123456789012", "XXXX"
|
||||
// storage: nonempty
|
||||
// storage_empty -> false
|
||||
// set(bytes): 0x20, 3, "abc"
|
||||
// storage: nonempty
|
||||
// storage_empty -> false
|
||||
// set(bytes): 0x20, 0
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
// set(bytes): 0x20, 3, "abc"
|
||||
// storage: nonempty
|
||||
// storage_empty -> false
|
||||
// set(bytes): 0x20, 36, "12345678901234567890123456789012", "XXXX"
|
||||
// storage: nonempty
|
||||
// storage_empty -> false
|
||||
// set(bytes): 0x20, 0
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
// set(bytes): 0x20, 66, "12345678901234567890123456789012", "12345678901234567890123456789012", "12"
|
||||
// storage: nonempty
|
||||
// storage_empty -> false
|
||||
// set(bytes): 0x20, 3, "abc"
|
||||
// storage: nonempty
|
||||
// storage_empty -> false
|
||||
// set(bytes): 0x20, 0
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
|
||||
@ -23,13 +23,13 @@ contract c {
|
||||
// ====
|
||||
// compileViaYul: also
|
||||
// ----
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
// set(uint256,bytes,uint256): 12, 0x60, 13, 33, "12345678901234567890123456789012", "3" -> true
|
||||
// test(uint256): 32 -> "3"
|
||||
// storage: nonempty
|
||||
// storage_empty -> false
|
||||
// copy() -> true
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
// set(uint256,bytes,uint256): 12, 0x60, 13, 33, "12345678901234567890123456789012", "3" -> true
|
||||
// storage: nonempty
|
||||
// storage_empty -> false
|
||||
// del() -> true
|
||||
// storage: empty
|
||||
// storage_empty -> true
|
||||
|
||||
@ -290,8 +290,6 @@ struct FunctionCall
|
||||
LowLevel,
|
||||
/// Marks a library deployment call.
|
||||
Library,
|
||||
/// Check that the storage of the current contract is empty or non-empty.
|
||||
Storage,
|
||||
/// Call to a builtin.
|
||||
Builtin
|
||||
};
|
||||
|
||||
@ -85,21 +85,6 @@ 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
|
||||
BOOST_THROW_EXCEPTION(TestParserError("Expected \"empty\" or \"nonempty\"."));
|
||||
call.kind = FunctionCall::Kind::Storage;
|
||||
m_scanner.scanNextToken();
|
||||
}
|
||||
else
|
||||
{
|
||||
bool lowLevelCall = false;
|
||||
|
||||
@ -958,28 +958,6 @@ 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()
|
||||
|
||||
}
|
||||
|
||||
@ -60,20 +60,6 @@ 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;
|
||||
|
||||
Loading…
Reference in New Issue
Block a user