Skip to content

Commit

Permalink
test: Add declarative StateTest fixture
Browse files Browse the repository at this point in the history
  • Loading branch information
chfast committed Apr 5, 2023
1 parent 40aeb62 commit d4b6371
Show file tree
Hide file tree
Showing 3 changed files with 125 additions and 0 deletions.
2 changes: 2 additions & 0 deletions test/unittests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ target_sources(
state_mpt_test.cpp
state_new_account_address_test.cpp
state_rlp_test.cpp
state_transition.hpp
state_transition.cpp
statetest_loader_block_info_test.cpp
statetest_loader_test.cpp
statetest_loader_tx_test.cpp
Expand Down
54 changes: 54 additions & 0 deletions test/unittests/state_transition.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
// evmone: Fast Ethereum Virtual Machine implementation
// Copyright 2023 The evmone Authors.
// SPDX-License-Identifier: Apache-2.0

#include "state_transition.hpp"

namespace evmone::test
{
void state_transition::TearDown()
{
auto& state = pre;
const auto res = evmone::state::transition(state, block, tx, EVMC_CANCUN, vm);
ASSERT_TRUE(holds_alternative<TransactionReceipt>(res))
<< std::get<std::error_code>(res).message();
const auto& receipt = std::get<TransactionReceipt>(res);

EXPECT_EQ(receipt.status, expect.status);
if (expect.gas_used.has_value())
{
EXPECT_EQ(receipt.gas_used, *expect.gas_used);
}

for (const auto& [addr, expected_acc] : expect.post)
{
const auto acc = state.find(addr);
if (!expected_acc.exists)
{
EXPECT_EQ(acc, nullptr) << "account " << addr << " should not exist";
}
else
{
ASSERT_NE(acc, nullptr) << "account " << addr << " should exist";
if (expected_acc.nonce.has_value())
{
EXPECT_EQ(acc->nonce, *expected_acc.nonce);
}
if (expected_acc.balance.has_value())
{
EXPECT_EQ(acc->balance, *expected_acc.balance);
}
for (const auto& [key, value] : expected_acc.storage)
{
EXPECT_EQ(acc->storage.at(key).current, value);
}
for (const auto& [key, value] : acc->storage)
{
// Find unexpected storage keys. This will also report entries with value 0.
EXPECT_TRUE(expected_acc.storage.contains(key))
<< "unexpected storage key " << key << "=" << value.current << " in " << addr;
}
}
}
}
} // namespace evmone::test
69 changes: 69 additions & 0 deletions test/unittests/state_transition.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
// evmone: Fast Ethereum Virtual Machine implementation
// Copyright 2023 The evmone Authors.
// SPDX-License-Identifier: Apache-2.0
#pragma once

#include <evmone/evmone.h>
#include <gtest/gtest.h>
#include <test/state/host.hpp>

#pragma GCC diagnostic ignored "-Wmissing-field-initializers"

namespace evmone::test
{
using namespace evmone;
using namespace evmone::state;

/// Fixture to defining test cases in form similar to JSON State Tests.
///
/// It takes the "pre" state and produces "post" state by applying the defined "tx" transaction.
/// Then expectations declared in "except" are checked in the "post" state.
class state_transition : public testing::Test
{
protected:
/// The default sender address of the test transaction.
/// Private key: 0xa45355879.
static constexpr auto Sender = 0xe100DeB58f38F7fd62d14E37e2Fe9ce019Aa001e_address;

/// The default destination address of the test transaction.
static constexpr auto To = 0xc0de_address;

static inline evmc::VM vm{evmc_create_evmone()};

struct ExpectedAccount
{
bool exists = true;
std::optional<uint64_t> nonce;
std::optional<intx::uint256> balance;
std::unordered_map<bytes32, bytes32> storage;
};

struct Expectation
{
evmc_status_code status = EVMC_SUCCESS;
std::optional<int64_t> gas_used;

std::unordered_map<address, ExpectedAccount> post;
};


BlockInfo block{.gas_limit = 1'000'000, .base_fee = 1000};
Transaction tx{.gas_limit = block.gas_limit,
.max_gas_price = block.base_fee,
.sender = Sender,
.to = To};
State pre;
Expectation expect;

state_transition()
{
pre.insert(
tx.sender, {.nonce = 1, .balance = tx.gas_limit * tx.max_gas_price + tx.value + 1});
pre.insert(*tx.to, {.nonce = 1});
}

/// The test runner.
void TearDown() override;
};

} // namespace evmone::test

0 comments on commit d4b6371

Please sign in to comment.