Skip to content

Commit

Permalink
Merge pull request #221 from ethereum/vmtester
Browse files Browse the repository at this point in the history
vmtester: Drop CLI11 dependency
  • Loading branch information
chfast authored Mar 25, 2019
2 parents fd1d182 + d5aad34 commit c1ee3c0
Show file tree
Hide file tree
Showing 2 changed files with 135 additions and 42 deletions.
53 changes: 25 additions & 28 deletions test/vmtester/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,37 +1,34 @@
# EVMC: Ethereum Client-VM Connector API.
# Copyright 2018 The EVMC Authors.
# Licensed under the Apache License, Version 2.0. See the LICENSE file.
# Copyright 2019 The EVMC Authors.
# Licensed under the Apache License, Version 2.0.

include(GNUInstallDirs)

hunter_add_package(CLI11)
find_package(CLI11)

add_executable(evmc-vmtester vmtester.hpp vmtester.cpp tests.cpp)
set_target_properties(evmc-vmtester PROPERTIES RUNTIME_OUTPUT_DIRECTORY ..)
target_link_libraries(evmc-vmtester PRIVATE evmc loader evmc-example-host GTest::gtest CLI11::CLI11)
target_link_libraries(evmc-vmtester PRIVATE evmc loader evmc-example-host GTest::gtest)
set_source_files_properties(vmtester.cpp PROPERTIES COMPILE_DEFINITIONS PROJECT_VERSION=\"${PROJECT_VERSION}\")


install(TARGETS evmc-vmtester RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})

add_test(NAME vmtester-help
COMMAND evmc-vmtester --help
)
set_tests_properties(vmtester-help PROPERTIES
PASS_REGULAR_EXPRESSION "Options:"
)

add_test(NAME vmtester-nonexistingvm
COMMAND evmc-vmtester nonexistingvm
)
set_tests_properties(vmtester-nonexistingvm PROPERTIES
WILL_FAIL TRUE
FAIL_REGULAR_EXPRESSION "no such file"
)

add_test(NAME vmtester-novm
COMMAND evmc-vmtester
)
set_tests_properties(vmtester-novm PROPERTIES
WILL_FAIL TRUE
FAIL_REGULAR_EXPRESSION "required but missing"
)
add_test(NAME vmtester-help COMMAND evmc-vmtester --version --help)
set_tests_properties(vmtester-help PROPERTIES PASS_REGULAR_EXPRESSION "Usage:")

add_test(NAME vmtester-nonexistingvm COMMAND evmc-vmtester nonexistingvm)
set_tests_properties(vmtester-nonexistingvm PROPERTIES PASS_REGULAR_EXPRESSION "Cannot open")

add_test(NAME vmtester-noarg COMMAND evmc-vmtester)
set_tests_properties(vmtester-noarg PROPERTIES PASS_REGULAR_EXPRESSION "is required")

add_test(NAME vmtester-too-many-args COMMAND evmc-vmtester a b)
set_tests_properties(vmtester-too-many-args PROPERTIES PASS_REGULAR_EXPRESSION "Unexpected")

add_test(NAME vmtester-version COMMAND evmc-vmtester --version)
set_tests_properties(vmtester-version PROPERTIES PASS_REGULAR_EXPRESSION ${PROJECT_VERSION})

add_test(NAME vmtester-unknown-option COMMAND evmc-vmtester --verbose)
set_tests_properties(vmtester-unknown-option PROPERTIES PASS_REGULAR_EXPRESSION "Unknown")

add_test(NAME vmtester-option-long-prefix COMMAND evmc-vmtester ---)
set_tests_properties(vmtester-option-long-prefix PROPERTIES PASS_REGULAR_EXPRESSION "Unknown")
124 changes: 110 additions & 14 deletions test/vmtester/vmtester.cpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
// EVMC: Ethereum Client-VM Connector API.
// Copyright 2018 The EVMC Authors.
// Licensed under the Apache License, Version 2.0. See the LICENSE file.
// Copyright 2019 The EVMC Authors.
// Licensed under the Apache License, Version 2.0.

#include "vmtester.hpp"

#include <evmc/loader.h>

#include <CLI/CLI.hpp>

#include <iostream>
#include <memory>

Expand All @@ -28,29 +26,127 @@ evmc_instance* get_vm_instance()
return vm.get();
}

class cli_parser
{
public:
const char* const app_name = nullptr;
const char* const app_version = nullptr;

std::vector<std::string> args_names;
std::vector<std::string> args;

cli_parser(const char* app_name,
const char* app_version,
std::vector<std::string> args_names) noexcept
: app_name{app_name}, app_version{app_version}, args_names{std::move(args_names)}
{
args.reserve(this->args_names.size());
}

/// Parses the command line arguments.
///
/// It recognize --help and --version 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)
{
bool help = false;
bool version = false;
size_t num_args = 0;
for (int i = 1; i < argc; ++i)
{
auto arg = std::string{argv[i]};

auto x = arg.find_first_not_of('-');
if (x == 0) // Argument.
{
++num_args;
if (num_args > args_names.size())
{
err << "Unexpected argument \"" << arg << "\"\n";
return -1;
}
args.emplace_back(std::move(arg));
continue;
}
else if (x <= 2)
{
arg.erase(0, x);

if (arg == "version")
{
version = true;
continue;
}
if (arg == "help")
{
help = true;
continue;
}
}

err << "Unknown option \"" << argv[i] << "\"\n";
return -1;
}

out << app_name << " " << app_version << "\n";

if (help)
{
out << "Usage: " << argv[0];
for (const auto& name : args_names)
out << " " << name;
out << "\n";
return 0;
}

if (version)
return 0;

if (num_args < args_names.size())
{
for (auto i = num_args; i < args_names.size(); ++i)
err << "The " << args_names[i] << " argument is required.\n";
err << "Run with --help for more information.\n";
return -1;
}

return 1;
}
};

int main(int argc, char* argv[])
{
try
{
std::string vm_path;

CLI::App app{"EVMC VM Tester"};
app.add_option("vm", vm_path, "Path to the VM shared library to be tested");
testing::InitGoogleTest(&argc, argv);
CLI11_PARSE(app, argc, argv);

std::cout << "Testing " << vm_path << "\n";
auto cli = cli_parser{"EVMC VM Tester", PROJECT_VERSION, {"MODULE"}};

const auto error_code = cli.parse(argc, argv, std::cout, std::cerr);
if (error_code <= 0)
return error_code;

const auto& evmc_module = cli.args[0];
std::cout << "Testing " << evmc_module << "\n";
evmc_loader_error_code ec;
create_fn = evmc_load(vm_path.c_str(), &ec);
create_fn = evmc_load(evmc_module.c_str(), &ec);
switch (ec)
{
case EVMC_LOADER_SUCCESS:
break;
case EVMC_LOADER_CANNOT_OPEN:
std::cerr << "Cannot open " << vm_path << "\n";
std::cerr << "Cannot open " << evmc_module << "\n";
return static_cast<int>(ec);
case EVMC_LOADER_SYMBOL_NOT_FOUND:
std::cerr << "EVMC create function not found in " << vm_path << "\n";
std::cerr << "EVMC create function not found in " << evmc_module << "\n";
return static_cast<int>(ec);
case EVMC_LOADER_INVALID_ARGUMENT:
std::cerr << "Invalid argument: \"" << evmc_module << "\"\n";
return static_cast<int>(ec);
default:
std::cerr << "Unexpected error in evmc_load(): " << ec << "\n";
Expand All @@ -63,6 +159,6 @@ int main(int argc, char* argv[])
catch (const std::exception& ex)
{
std::cerr << ex.what() << "\n";
return 1;
return -2;
}
}

0 comments on commit c1ee3c0

Please sign in to comment.