Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test: ExportableFixture for JSON tests exporting #821

Merged
merged 4 commits into from
Feb 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions test/integration/statetest/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,15 @@ set_tests_properties(
FIXTURES_SETUP EXPORT_JSON_TESTS
)

add_test(
NAME ${PREFIX}/export_to_json_created_files
COMMAND ${CMAKE_COMMAND} -E sha256sum ${EXPORT_DIR}/state_transition/block/known_block_hash.json
gumb0 marked this conversation as resolved.
Show resolved Hide resolved
)
set_tests_properties(
${PREFIX}/export_to_json_created_files PROPERTIES
FIXTURES_REQUIRED EXPORT_JSON_TESTS
)

add_test(
NAME ${PREFIX}/execute_exported_tests
# TODO: Broken exported tests are filtered out.
Expand Down
4 changes: 3 additions & 1 deletion test/unittests/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ target_sources(
analysis_test.cpp
blockchaintest_loader_test.cpp
bytecode_test.cpp
eof_stack_validation_test.cpp
eof_validation_stack_test.cpp
eof_test.cpp
eof_validation.hpp
eof_validation.cpp
Expand Down 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
46 changes: 46 additions & 0 deletions test/unittests/exportable_fixture.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
// 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 <regex>

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 suite_name{test_info.test_suite_name()};

const auto stem = fs::path{test_info.file()}.stem().string();
const std::regex re{suite_name + "_(.*)_test"};
gumb0 marked this conversation as resolved.
Show resolved Hide resolved
std::smatch m;
const auto sub_suite_name = std::regex_match(stem, m, re) ? m[1] : std::string{};

const auto dir = fs::path{export_dir} / suite_name / sub_suite_name;

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_file_path = get_export_test_path(test_info, export_dir).string();
}
}
} // 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::string_view export_test_name;
std::string export_file_path;

ExportableFixture();
};
} // namespace evmone::test
41 changes: 5 additions & 36 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,14 @@ 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_file_path.empty())
export_state_test(receipt, state);
}
} // namespace

void state_transition::export_state_test(
const TransactionReceipt& receipt, const State& post, std::string_view export_dir)
void state_transition::export_state_test(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 +167,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;
std::ofstream{export_file_path} << 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