[isoltest] Replace storage command with 'storage_empty' builtin.

This commit is contained in:
Alexander Arlt 2021-01-07 22:45:19 -05:00
parent 5852972ec1
commit 1f2711b0aa
28 changed files with 79 additions and 120 deletions

View File

@ -27,6 +27,7 @@
#include <algorithm>
#include <cctype>
#include <fstream>
#include <functional>
#include <memory>
#include <optional>
#include <stdexcept>
@ -124,6 +125,12 @@ void SemanticTest::initializeBuiltins()
{
return util::toBigEndian(u256(0x1234));
};
soltestAssert(m_builtins.count("storageEmpty") == 0, "");
m_builtins["storageEmpty"] = [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)
@ -222,16 +229,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;

View File

@ -41,17 +41,17 @@ contract c {
// ====
// compileViaYul: also
// ----
// storage: empty
// storageEmpty -> 1
// test_short() -> 1780731860627700044960722568376587075150542249149356309979516913770823710
// gas legacy: 110938
// gas legacyOptimized: 109706
// storage: nonempty
// storageEmpty -> 0
// test_long() -> 67
// gas irOptimized: 134320
// gas legacy: 213590
// gas legacyOptimized: 211044
// storage: nonempty
// storageEmpty -> 0
// test_pop() -> 1780731860627700044960722568376592200742329637303199754547598369979433020
// gas legacy: 176030
// gas legacyOptimized: 173504
// storage: nonempty
// storageEmpty -> 0

View File

@ -40,9 +40,9 @@ contract c {
// gas irOptimized: 2470372
// gas legacy: 2288641
// gas legacyOptimized: 2258654
// storage: empty
// storageEmpty -> 1
// clear() -> 0, 0
// gas irOptimized: 1852821
// gas legacy: 1727169
// gas legacyOptimized: 1698931
// storage: empty
// storageEmpty -> 1

View File

@ -21,4 +21,4 @@ contract c {
// setData1(uint256,uint256,uint256): 0, 0, 0 ->
// copyStorageStorage() ->
// getData2(uint256): 0 -> 0, 0
// storage: empty
// storageEmpty -> 1

View File

@ -22,4 +22,4 @@ contract c {
// gas irOptimized: 257752
// gas legacy: 255936
// gas legacyOptimized: 254359
// storage: empty
// storageEmpty -> 1

View File

@ -14,10 +14,10 @@ contract c {
// gas irOptimized: 163929
// gas legacy: 164121
// gas legacyOptimized: 163766
// storage: nonempty
// storageEmpty -> 0
// copy(uint256,uint256): 1, 2 -> true
// storage: nonempty
// storageEmpty -> 0
// copy(uint256,uint256): 99, 1 -> true
// storage: nonempty
// storageEmpty -> 0
// copy(uint256,uint256): 99, 2 -> true
// storage: empty
// storageEmpty -> 1

View File

@ -43,4 +43,4 @@ contract C {
// g() -> 0x40, 0xc0, 0x49, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738393031323334353637383930313233343536373839303120, 0x3132333435363738390000000000000000000000000000000000000000000000, 0x11, 0x3132333435363738393233343536373839000000000000000000000000000000
// gas legacy: 100595
// h() -> 0x40, 0x60, 0x00, 0x00
// storage: empty
// storageEmpty -> 1

View File

@ -12,6 +12,6 @@ contract c {
// gas irOptimized: 163680
// gas legacy: 163756
// gas legacyOptimized: 163596
// storage: nonempty
// storageEmpty -> 0
// reset() -> true
// storage: empty
// storageEmpty -> 1

View File

@ -7,6 +7,6 @@ contract c {
// compileViaYul: also
// ----
// (): 7 ->
// storage: nonempty
// storageEmpty -> 0
// del(): 7 -> true
// storage: empty
// storageEmpty -> 1

View File

@ -14,13 +14,13 @@ contract c {
// ====
// compileViaYul: also
// ----
// storage: empty
// storageEmpty -> 1
// fill() ->
// gas irOptimized: 535098
// gas legacy: 504373
// gas legacyOptimized: 499648
// storage: nonempty
// storageEmpty -> 0
// halfClear() ->
// storage: nonempty
// storageEmpty -> 0
// fullClear() ->
// storage: empty
// storageEmpty -> 1

View File

@ -16,11 +16,11 @@ contract c {
// ====
// compileViaYul: also
// ----
// storage: empty
// storageEmpty -> 1
// fill() -> 8
// gas irOptimized: 168980
// gas legacy: 165456
// gas legacyOptimized: 164387
// storage: nonempty
// storageEmpty -> 0
// clear() ->
// storage: empty
// storageEmpty -> 1

View File

@ -11,11 +11,11 @@ contract c {
// compileToEwasm: also
// compileViaYul: also
// ----
// storage: empty
// storageEmpty -> 1
// fill() ->
// gas irOptimized: 423878
// gas legacy: 429460
// gas legacyOptimized: 425520
// storage: nonempty
// storageEmpty -> 0
// clear() ->
// storage: empty
// storageEmpty -> 1

View File

@ -28,4 +28,4 @@ contract c {
// gas irOptimized: 2455497
// gas legacy: 2416722
// gas legacyOptimized: 2405396
// storage: empty
// storageEmpty -> 1

View File

@ -9,4 +9,4 @@ contract c {
// compileViaYul: also
// ----
// test() ->
// storage: empty
// storageEmpty -> 1

View File

@ -23,4 +23,4 @@ contract c {
// gas irOptimized: 527367
// gas legacy: 454080
// gas legacyOptimized: 443170
// storage: empty
// storageEmpty -> 1

View File

@ -23,4 +23,4 @@ contract c {
// gas irOptimized: 367121
// gas legacy: 320859
// gas legacyOptimized: 314681
// storage: empty
// storageEmpty -> 1

View File

@ -21,4 +21,4 @@ contract c {
// gas irOptimized: 445718
// gas legacy: 552064
// gas legacyOptimized: 533164
// storage: empty
// storageEmpty -> 1

View File

@ -20,4 +20,4 @@ contract c {
// gas irOptimized: 291114
// gas legacy: 372763
// gas legacyOptimized: 366846
// storage: empty
// storageEmpty -> 1

View File

@ -14,4 +14,4 @@ contract c {
// compileViaYul: also
// ----
// test() ->
// storage: empty
// storageEmpty -> 1

View File

@ -11,8 +11,8 @@ contract c {
// compileToEwasm: also
// compileViaYul: also
// ----
// storage: empty
// storageEmpty -> 1
// fill() ->
// storage: nonempty
// storageEmpty -> 0
// clear() ->
// storage: empty
// storageEmpty -> 1

View File

@ -0,0 +1,6 @@
contract StorageEmpty {
}
// ====
// compileViaYul: also
// ----
// storageEmpty -> 1

View File

@ -0,0 +1,10 @@
contract StorageNotEmpty {
uint256 x;
function set(uint256 _a) public { x = _a; }
}
// ====
// compileViaYul: also
// ----
// storageEmpty -> 1
// set(uint256): 1 ->
// storageEmpty -> 0

View File

@ -6,26 +6,26 @@ contract Test {
// compileViaYul: also
// ----
// set(bytes): 0x20, 3, "abc"
// storage: nonempty
// storageEmpty -> 0
// set(bytes): 0x20, 0
// storage: empty
// storageEmpty -> 1
// set(bytes): 0x20, 31, "1234567890123456789012345678901"
// storage: nonempty
// storageEmpty -> 0
// set(bytes): 0x20, 36, "12345678901234567890123456789012", "XXXX"
// storage: nonempty
// storageEmpty -> 0
// set(bytes): 0x20, 3, "abc"
// storage: nonempty
// storageEmpty -> 0
// set(bytes): 0x20, 0
// storage: empty
// storageEmpty -> 1
// set(bytes): 0x20, 3, "abc"
// storage: nonempty
// storageEmpty -> 0
// set(bytes): 0x20, 36, "12345678901234567890123456789012", "XXXX"
// storage: nonempty
// storageEmpty -> 0
// set(bytes): 0x20, 0
// storage: empty
// storageEmpty -> 1
// set(bytes): 0x20, 66, "12345678901234567890123456789012", "12345678901234567890123456789012", "12"
// storage: nonempty
// storageEmpty -> 0
// set(bytes): 0x20, 3, "abc"
// storage: nonempty
// storageEmpty -> 0
// set(bytes): 0x20, 0
// storage: empty
// storageEmpty -> 1

View File

@ -23,16 +23,16 @@ contract c {
// ====
// compileViaYul: also
// ----
// storage: empty
// storageEmpty -> 1
// set(uint256,bytes,uint256): 12, 0x60, 13, 33, "12345678901234567890123456789012", "3" -> true
// gas irOptimized: 124227
// gas legacy: 124736
// gas legacyOptimized: 124179
// test(uint256): 32 -> "3"
// storage: nonempty
// storageEmpty -> 0
// copy() -> true
// storage: empty
// storageEmpty -> 1
// set(uint256,bytes,uint256): 12, 0x60, 13, 33, "12345678901234567890123456789012", "3" -> true
// storage: nonempty
// storageEmpty -> 0
// del() -> true
// storage: empty
// storageEmpty -> 1

View File

@ -294,9 +294,8 @@ 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.
/// Builtins get registered in `SemanticTest::initializeBuiltins()`.
Builtin
};
Kind kind = Kind::Regular;

View File

@ -106,21 +106,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;

View File

@ -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()
}

View File

@ -61,23 +61,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 =
_renderMode == RenderMode::ActualValuesExpectedGas ?
m_rawBytes.front() == 0 :
m_call.expectations.rawBytes().front() == 0;
string output = isEmpty ? "empty" : "nonempty";
if (_renderMode == RenderMode::ActualValuesExpectedGas && !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;