-
Notifications
You must be signed in to change notification settings - Fork 298
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
EVM test tool #85
EVM test tool #85
Changes from all commits
3dae579
ff85e3d
b481109
e86de93
f719370
558f1fe
644d4ab
3a74360
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,179 @@ | ||
// evmone: Fast Ethereum Virtual Machine implementation | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would probably be better if this file were in a separate directory, not There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. There are more changes to dir structure needed, so I left it for another time. Preferably the Maybe just get rid of |
||
// Copyright 2019 The evmone Authors. | ||
// Licensed under the Apache License, Version 2.0. | ||
|
||
#include "vm_loader.hpp" | ||
#include <evmc/loader.h> | ||
#include <gtest/gtest.h> | ||
#include <iostream> | ||
#include <string> | ||
#include <vector> | ||
|
||
/// The loaded EVMC module. | ||
static evmc::vm evmc_module; | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It would be less confusing if this and There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It was planned like that, but it gets tricky because |
||
|
||
evmc::vm& get_vm() noexcept | ||
{ | ||
return evmc_module; | ||
} | ||
|
||
/// Simple and copy&paste distributable CLI parser. | ||
/// | ||
/// TODO: Originally taken from EVMC and modified here. Copy it back. | ||
class cli_parser | ||
{ | ||
public: | ||
using preprocessor_fn = void (*)(int*, char**); | ||
|
||
const char* const application_name = nullptr; | ||
const char* const application_version = nullptr; | ||
const char* const application_description = nullptr; | ||
|
||
std::vector<std::string> arguments_names; | ||
std::vector<std::string> arguments; | ||
|
||
preprocessor_fn preprocessor = [](int*, char**) {}; | ||
|
||
cli_parser(const char* app_name, const char* app_version, const char* app_description, | ||
std::vector<std::string> args_names) noexcept | ||
: application_name{app_name}, | ||
application_version{app_version}, | ||
application_description{app_description}, | ||
arguments_names{std::move(args_names)} | ||
{ | ||
arguments.reserve(this->arguments_names.size()); | ||
} | ||
|
||
/// Sets the preprocessor and enables preprocessing. | ||
/// | ||
/// The preprocessor runs on provided arguments before the parsing is done. | ||
/// It is allowed to modify the arguments and/or generate other output. | ||
/// | ||
/// @param fn The preprocessor function. | ||
void set_preprocessor(preprocessor_fn fn) noexcept { preprocessor = fn; } | ||
|
||
/// Parses the command line arguments. | ||
/// | ||
/// It recognize --help and --version built-in options and output for these is sent | ||
/// to the @p out output stream. | ||
/// Errors are sent to the @p err output stream. | ||
/// | ||
/// @return Negative value in case of error, | ||
/// 0 in case --help or --version was provided and the program should terminate, | ||
/// positive value in case the program should continue. | ||
int parse(int argc, char* argv[], std::ostream& out, std::ostream& err) | ||
{ | ||
out << application_name << " " << application_version << "\n\n"; | ||
|
||
const auto should_exit = handle_builtin_options(argc, argv, out); | ||
|
||
// Run preprocessor after the output from built-in options. | ||
preprocessor(&argc, argv); | ||
|
||
if (should_exit) | ||
return 0; | ||
|
||
size_t num_args = 0; | ||
for (int i = 1; i < argc; ++i) | ||
{ | ||
auto arg = std::string{argv[i]}; | ||
|
||
const auto num_dashes = arg.find_first_not_of('-'); | ||
if (num_dashes == 0) // Argument. | ||
{ | ||
++num_args; | ||
if (num_args > arguments_names.size()) | ||
{ | ||
err << "Unexpected argument \"" << arg << "\"\n"; | ||
return -1; | ||
} | ||
arguments.emplace_back(std::move(arg)); | ||
continue; | ||
} | ||
|
||
err << "Unknown option \"" << argv[i] << "\"\n"; | ||
return -1; | ||
} | ||
|
||
if (num_args < arguments_names.size()) | ||
{ | ||
for (auto i = num_args; i < arguments_names.size(); ++i) | ||
err << "The " << arguments_names[i] << " argument is required.\n"; | ||
err << "Run with --help for more information.\n"; | ||
return -1; | ||
} | ||
|
||
return 1; | ||
} | ||
|
||
private: | ||
bool handle_builtin_options(int argc, char* argv[], std::ostream& out) | ||
{ | ||
using namespace std::string_literals; | ||
|
||
auto help = false; | ||
auto version = false; | ||
|
||
for (int i = 1; i < argc; ++i) | ||
{ | ||
help |= argv[i] == "--help"s || argv[i] == "-h"s; | ||
version |= argv[i] == "--version"s; | ||
} | ||
|
||
if (help) | ||
{ | ||
out << "Usage: " << argv[0]; | ||
for (const auto& name : arguments_names) | ||
out << " " << name; | ||
out << "\n\n"; | ||
return true; | ||
} | ||
|
||
if (version) | ||
{ | ||
if (application_description) | ||
out << application_description << "\n"; | ||
return true; | ||
} | ||
|
||
return false; | ||
} | ||
}; | ||
|
||
int main(int argc, char* argv[]) | ||
{ | ||
try | ||
{ | ||
auto cli = cli_parser{"EVM Test", PROJECT_VERSION, | ||
"Testing tool for EVMC-compatible Ethereum Virtual Machine implementations.\n" | ||
"Powered by the evmone project.\n\n" | ||
"EVMC: https://github.com/ethereum/evmc\n" | ||
"evmone: https://github.com/ethereum/evmone", | ||
{"MODULE"}}; | ||
cli.set_preprocessor(testing::InitGoogleTest); | ||
|
||
if (const auto error_code = cli.parse(argc, argv, std::cout, std::cerr); error_code <= 0) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. cool, C++17 |
||
return error_code; | ||
|
||
const auto& evmc_config = cli.arguments[0]; | ||
evmc_loader_error_code ec; | ||
evmc_module = evmc::vm{evmc_load_and_configure(evmc_config.c_str(), &ec)}; | ||
|
||
if (ec != EVMC_LOADER_SUCCESS) | ||
{ | ||
if (const auto error = evmc_last_error_msg()) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This could be just
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ah I see |
||
std::cerr << "EVMC loading error: " << error << "\n"; | ||
else | ||
std::cerr << "EVMC loading error " << ec << "\n"; | ||
return static_cast<int>(ec); | ||
} | ||
|
||
std::cout << "Testing " << evmc_config << "\n\n"; | ||
return RUN_ALL_TESTS(); | ||
} | ||
catch (const std::exception& ex) | ||
{ | ||
std::cerr << ex.what() << "\n"; | ||
return -2; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
// evmone: Fast Ethereum Virtual Machine implementation | ||
// Copyright 2019 The evmone Authors. | ||
// Licensed under the Apache License, Version 2.0. | ||
#pragma once | ||
|
||
#include <evmc/evmc.hpp> | ||
|
||
evmc::vm& get_vm() noexcept; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
// evmone: Fast Ethereum Virtual Machine implementation | ||
// Copyright 2019 The evmone Authors. | ||
// Licensed under the Apache License, Version 2.0. | ||
|
||
#include "vm_loader.hpp" | ||
#include <evmone/evmone.h> | ||
|
||
evmc::vm& get_vm() noexcept | ||
{ | ||
static auto vm = evmc::vm{evmc_create_evmone()}; | ||
return vm; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At the bare minimum extending this section on build instruction if it is possible to only build this without evmone to be used by other projects would be useful.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not possible right now. I need another round of CMake changes to re-tune build options.