Skip to content

Commit

Permalink
test: ExportableFixture for JSON tests exporting (#821)
Browse files Browse the repository at this point in the history
Extract utils for JSON tests exporting to abstract `ExportableFixture`.
  • Loading branch information
chfast authored Feb 21, 2024
2 parents 34c0169 + 5de76a6 commit 5492627
Show file tree
Hide file tree
Showing 7 changed files with 85 additions and 42 deletions.
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
)
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"};
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

0 comments on commit 5492627

Please sign in to comment.