diff --git a/test/integration/statetest/CMakeLists.txt b/test/integration/statetest/CMakeLists.txt index c6ce9dced9..46b668d75d 100644 --- a/test/integration/statetest/CMakeLists.txt +++ b/test/integration/statetest/CMakeLists.txt @@ -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. diff --git a/test/unittests/CMakeLists.txt b/test/unittests/CMakeLists.txt index 5dc1d5899b..a0b43159cc 100644 --- a/test/unittests/CMakeLists.txt +++ b/test/unittests/CMakeLists.txt @@ -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 @@ -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 diff --git a/test/unittests/eof_stack_validation_test.cpp b/test/unittests/eof_validation_stack_test.cpp similarity index 100% rename from test/unittests/eof_stack_validation_test.cpp rename to test/unittests/eof_validation_stack_test.cpp diff --git a/test/unittests/exportable_fixture.cpp b/test/unittests/exportable_fixture.cpp new file mode 100644 index 0000000000..316189a52a --- /dev/null +++ b/test/unittests/exportable_fixture.cpp @@ -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 +#include + +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 diff --git a/test/unittests/exportable_fixture.hpp b/test/unittests/exportable_fixture.hpp new file mode 100644 index 0000000000..892c544edb --- /dev/null +++ b/test/unittests/exportable_fixture.hpp @@ -0,0 +1,18 @@ +// evmone: Fast Ethereum Virtual Machine implementation +// Copyright 2024 The evmone Authors. +// SPDX-License-Identifier: Apache-2.0 +#pragma once + +#include + +namespace evmone::test +{ +class ExportableFixture : public testing::Test +{ +protected: + std::string_view export_test_name; + std::string export_file_path; + + ExportableFixture(); +}; +} // namespace evmone::test diff --git a/test/unittests/state_transition.cpp b/test/unittests/state_transition.cpp index 35a1ad0e78..65406772a7 100644 --- a/test/unittests/state_transition.cpp +++ b/test/unittests/state_transition.cpp @@ -2,11 +2,6 @@ // 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 #include @@ -14,8 +9,6 @@ #include #include -namespace fs = std::filesystem; - namespace evmone::test { void state_transition::SetUp() @@ -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); @@ -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 diff --git a/test/unittests/state_transition.hpp b/test/unittests/state_transition.hpp index a7e9a383aa..c609b87e9c 100644 --- a/test/unittests/state_transition.hpp +++ b/test/unittests/state_transition.hpp @@ -3,8 +3,8 @@ // SPDX-License-Identifier: Apache-2.0 #pragma once +#include "exportable_fixture.hpp" #include -#include #include #include @@ -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. @@ -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