Skip to content

Commit

Permalink
PoC: ExportableFixture
Browse files Browse the repository at this point in the history
  • Loading branch information
chfast committed Feb 14, 2024
1 parent be459cc commit e9f8876
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 73 deletions.
2 changes: 2 additions & 0 deletions test/unittests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ target_sources(
evmmax_secp256k1_test.cpp
evmone_test.cpp
execution_state_test.cpp
exportable_fixture.hpp
exportable_fixture.cpp
instructions_test.cpp
state_block_test.cpp
state_bloom_filter_test.cpp
Expand Down
35 changes: 5 additions & 30 deletions test/unittests/eof_validation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,37 +2,13 @@
// Copyright 2024 The evmone Authors.
// SPDX-License-Identifier: Apache-2.0

#ifdef _MSC_VER
// Disable warning C4996: 'getenv': This function or variable may be unsafe.
#define _CRT_SECURE_NO_WARNINGS
#endif

#include "eof_validation.hpp"
#include <test/statetest/statetest.hpp>
#include <fstream>

namespace fs = std::filesystem;

namespace evmone::test
{
namespace
{
/// Creates the file path for the exported test based on its name.
fs::path get_export_test_path(const testing::TestInfo& test_info, std::string_view export_dir)
{
const std::string_view test_suite_name{test_info.test_suite_name()};

const auto stem = fs::path{test_info.file()}.stem().string();
auto filename = std::string_view{stem};
if (filename.ends_with("_test"))
filename.remove_suffix(5);

const auto dir = fs::path{export_dir} / test_suite_name / filename;

fs::create_directories(dir);
return dir / (std::string{test_info.name()} + ".json");
}

std::string_view get_tests_error_message(EOFValidationError err) noexcept
{
switch (err)
Expand Down Expand Up @@ -119,14 +95,13 @@ void eof_validation::TearDown()
<< hex(test_case.container);
}

if (const auto export_dir = std::getenv("EVMONE_EXPORT_TESTS"); export_dir != nullptr)
export_eof_validation_test(export_dir);
if (export_out)
export_eof_validation_test();
}

void eof_validation::export_eof_validation_test(std::string_view export_dir)
void eof_validation::export_eof_validation_test()
{
const auto& test_info = *testing::UnitTest::GetInstance()->current_test_info();
const std::string test_name = test_info.name();
const auto test_name = std::string{export_test_name};

json::json j;
auto& jt = j[test_name];
Expand All @@ -151,6 +126,6 @@ void eof_validation::export_eof_validation_test(std::string_view export_dir)
}
}

std::ofstream{get_export_test_path(test_info, export_dir)} << std::setw(2) << j;
*export_out << std::setw(2) << j;
}
} // namespace evmone::test
7 changes: 4 additions & 3 deletions test/unittests/eof_validation.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
// SPDX-License-Identifier: Apache-2.0
#pragma once

#include "exportable_fixture.hpp"
#include <evmc/evmc.hpp>
#include <evmone/eof.hpp>
#include <evmone/evmone.h>
Expand All @@ -16,7 +17,7 @@ using evmc::bytes;
/// Fixture for defining test cases for EOF validation.
///
/// Each test contains multiple cases, which are validated during test teardown.
class eof_validation : public testing::Test
class eof_validation : public ExportableFixture

Check warning on line 20 in test/unittests/eof_validation.hpp

View check run for this annotation

Codecov / codecov/patch

test/unittests/eof_validation.hpp#L20

Added line #L20 was not covered by tests
{
protected:
/// EOF validation test case.
Expand Down Expand Up @@ -46,8 +47,8 @@ class eof_validation : public testing::Test
/// The test runner.
void TearDown() override;

/// Exports the test in the JSON EOF Test format in the given directory.
void export_eof_validation_test(std::string_view export_dir);
/// Exports the test in the JSON EOF Test format to the ExportableFixture::export_out.
void export_eof_validation_test();
};

} // namespace evmone::test
48 changes: 48 additions & 0 deletions test/unittests/exportable_fixture.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
// evmone: Fast Ethereum Virtual Machine implementation
// Copyright 2024 The evmone Authors.
// SPDX-License-Identifier: Apache-2.0

#ifdef _MSC_VER
// Disable warning C4996: 'getenv': This function or variable may be unsafe.
#define _CRT_SECURE_NO_WARNINGS
#endif

#include "exportable_fixture.hpp"
#include <filesystem>
#include <fstream>

namespace fs = std::filesystem;

namespace evmone::test
{
namespace
{
/// Creates the file path for the exported test based on its name.
fs::path get_export_test_path(const testing::TestInfo& test_info, std::string_view export_dir)
{
const std::string_view test_suite_name{test_info.test_suite_name()};

const auto stem = fs::path{test_info.file()}.stem().string();
auto filename = std::string_view{stem};
if (filename.starts_with(test_suite_name))
filename.remove_prefix(test_suite_name.size() + 1);
if (filename.ends_with("_test"))
filename.remove_suffix(5);

const auto dir = fs::path{export_dir} / test_suite_name / filename;

fs::create_directories(dir);
return dir / (std::string{test_info.name()} + ".json");
}
} // namespace

ExportableFixture::ExportableFixture()
{
if (const auto export_dir = std::getenv("EVMONE_EXPORT_TESTS"); export_dir != nullptr)
{
const auto& test_info = *testing::UnitTest::GetInstance()->current_test_info();
export_test_name = test_info.name();
export_out = std::make_unique<std::fstream>(get_export_test_path(test_info, export_dir));
}
}
} // namespace evmone::test
18 changes: 18 additions & 0 deletions test/unittests/exportable_fixture.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
// evmone: Fast Ethereum Virtual Machine implementation
// Copyright 2024 The evmone Authors.
// SPDX-License-Identifier: Apache-2.0
#pragma once

#include <gtest/gtest.h>

namespace evmone::test
{
class ExportableFixture : public testing::Test
{
protected:
std::unique_ptr<std::ostream> export_out;
std::string_view export_test_name;

ExportableFixture();
};
} // namespace evmone::test
40 changes: 5 additions & 35 deletions test/unittests/state_transition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,13 @@
// Copyright 2023 The evmone Authors.
// SPDX-License-Identifier: Apache-2.0

#ifdef _MSC_VER
// Disable warning C4996: 'getenv': This function or variable may be unsafe.
#define _CRT_SECURE_NO_WARNINGS
#endif

#include "state_transition.hpp"
#include <evmone/eof.hpp>
#include <test/state/mpt_hash.hpp>
#include <test/statetest/statetest.hpp>
#include <filesystem>
#include <fstream>

namespace fs = std::filesystem;

namespace evmone::test
{
void state_transition::SetUp()
Expand Down Expand Up @@ -138,38 +131,15 @@ void state_transition::TearDown()
EXPECT_TRUE(expect.post.contains(addr)) << "unexpected account " << addr;
}

if (const auto export_dir = std::getenv("EVMONE_EXPORT_TESTS"); export_dir != nullptr)
export_state_test(receipt, state, export_dir);
}

namespace
{
/// Creates the file path for the exported test based on its name.
fs::path get_export_test_path(const testing::TestInfo& test_info, std::string_view export_dir)
{
const std::string_view test_suite_name{test_info.test_suite_name()};

const auto stem = fs::path{test_info.file()}.stem().string();
auto filename = std::string_view{stem};
if (filename.starts_with(test_suite_name))
filename.remove_prefix(test_suite_name.size() + 1);
if (filename.ends_with("_test"))
filename.remove_suffix(5);

const auto dir = fs::path{export_dir} / test_suite_name / filename;

fs::create_directories(dir);
return dir / (std::string{test_info.name()} + ".json");
if (export_out)
export_state_test(receipt, state);
}
} // namespace

void state_transition::export_state_test(
const TransactionReceipt& receipt, const State& post, std::string_view export_dir)
const TransactionReceipt& receipt, const State& post)
{
const auto& test_info = *testing::UnitTest::GetInstance()->current_test_info();

json::json j;
auto& jt = j[test_info.name()];
auto& jt = j[export_test_name];

auto& jenv = jt["env"];
jenv["currentNumber"] = hex0x(block.number);
Expand Down Expand Up @@ -198,6 +168,6 @@ void state_transition::export_state_test(
jpost["hash"] = hex0x(mpt_hash(post.get_accounts()));
jpost["logs"] = hex0x(logs_hash(receipt.logs));

std::ofstream{get_export_test_path(test_info, export_dir)} << std::setw(2) << j;
*export_out << std::setw(2) << j;
}
} // namespace evmone::test
9 changes: 4 additions & 5 deletions test/unittests/state_transition.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
// SPDX-License-Identifier: Apache-2.0
#pragma once

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

Expand All @@ -17,7 +17,7 @@ using namespace evmone::state;
///
/// 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
class state_transition : public ExportableFixture
{
protected:
/// The default sender address of the test transaction.
Expand Down Expand Up @@ -91,9 +91,8 @@ class state_transition : public testing::Test
/// The test runner.
void TearDown() override;

/// Exports the test in the JSON State Test format in the given directory.
void export_state_test(
const TransactionReceipt& receipt, const State& post, std::string_view export_dir);
/// Exports the test in the JSON State Test format to ExportableFixture::export_out.
void export_state_test(const TransactionReceipt& receipt, const State& post);
};

} // namespace evmone::test

0 comments on commit e9f8876

Please sign in to comment.