mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-11 16:46:16 +00:00
Parallel test execution (#118)
This commit is contained in:
5
.github/workflows/build.yml
vendored
5
.github/workflows/build.yml
vendored
@@ -223,6 +223,11 @@ jobs:
|
||||
- platform: macOS x86_64
|
||||
runner: macos-13
|
||||
steps:
|
||||
- name: Checkout Source
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Download Test Config
|
||||
uses: pyTooling/download-artifact@v4
|
||||
with:
|
||||
|
||||
5
.gitmodules
vendored
5
.gitmodules
vendored
@@ -14,4 +14,7 @@
|
||||
path = deps/zlib
|
||||
url = https://github.com/madler/zlib.git
|
||||
branch = develop
|
||||
ignore = dirty
|
||||
ignore = dirty
|
||||
[submodule "deps/gtest-parallel"]
|
||||
path = deps/gtest-parallel
|
||||
url = https://github.com/google/gtest-parallel.git
|
||||
|
||||
@@ -95,7 +95,10 @@ if(MSVC)
|
||||
#/LTCG
|
||||
)
|
||||
|
||||
add_compile_definitions(_CRT_SECURE_NO_WARNINGS)
|
||||
add_compile_definitions(
|
||||
_CRT_SECURE_NO_WARNINGS
|
||||
_CRT_NONSTDC_NO_WARNINGS
|
||||
)
|
||||
endif()
|
||||
|
||||
##########################################
|
||||
|
||||
1
deps/gtest-parallel
vendored
Submodule
1
deps/gtest-parallel
vendored
Submodule
Submodule deps/gtest-parallel added at 96f4f90492
@@ -19,8 +19,13 @@ if(WIN32)
|
||||
add_dependencies(windows-emulator-test test-sample)
|
||||
endif()
|
||||
|
||||
set(PYTHON3_EXE "python3")
|
||||
if(CMAKE_SYSTEM_NAME MATCHES "Windows")
|
||||
set(PYTHON3_EXE "python")
|
||||
endif()
|
||||
|
||||
add_test(NAME windows-emulator-test
|
||||
COMMAND windows-emulator-test
|
||||
COMMAND "${PYTHON3_EXE}" "${PROJECT_SOURCE_DIR}/deps/gtest-parallel/gtest_parallel.py" ./windows-emulator-test
|
||||
WORKING_DIRECTORY "$<TARGET_FILE_DIR:windows-emulator-test>")
|
||||
|
||||
momo_targets_set_folder("tests" windows-emulator-test)
|
||||
momo_targets_set_folder("tests" windows-emulator-test)
|
||||
|
||||
@@ -56,6 +56,11 @@ namespace test
|
||||
|
||||
settings.application = "c:/test-sample.exe";
|
||||
settings.emulation_root = get_emulator_root();
|
||||
|
||||
settings.port_mappings[28970] = static_cast<uint16_t>(getpid());
|
||||
settings.path_mappings["C:\\a.txt"] =
|
||||
std::filesystem::temp_directory_path() / ("emulator-test-file-" + std::to_string(getpid()) + ".txt");
|
||||
|
||||
return windows_emulator{std::move(settings), std::move(callbacks)};
|
||||
}
|
||||
|
||||
|
||||
@@ -121,13 +121,13 @@ namespace
|
||||
throw std::runtime_error("Unknown socket protocol: " + std::to_string(win_protocol));
|
||||
}
|
||||
|
||||
std::vector<std::byte> convert_to_win_address(const network::address& a)
|
||||
std::vector<std::byte> convert_to_win_address(const windows_emulator& win_emu, const network::address& a)
|
||||
{
|
||||
if (a.is_ipv4())
|
||||
{
|
||||
win_sockaddr_in win_addr{};
|
||||
win_addr.sin_family = translate_host_to_win_address_family(a.get_family());
|
||||
win_addr.sin_port = htons(a.get_port());
|
||||
win_addr.sin_port = htons(win_emu.get_emulator_port(a.get_port()));
|
||||
memcpy(&win_addr.sin_addr, &a.get_in_addr().sin_addr, sizeof(win_addr.sin_addr));
|
||||
|
||||
const auto ptr = reinterpret_cast<std::byte*>(&win_addr);
|
||||
@@ -138,7 +138,7 @@ namespace
|
||||
{
|
||||
win_sockaddr_in6 win_addr{};
|
||||
win_addr.sin6_family = translate_host_to_win_address_family(a.get_family());
|
||||
win_addr.sin6_port = htons(a.get_port());
|
||||
win_addr.sin6_port = htons(win_emu.get_emulator_port(a.get_port()));
|
||||
|
||||
auto& addr = a.get_in6_addr();
|
||||
memcpy(&win_addr.sin6_addr, &addr.sin6_addr, sizeof(win_addr.sin6_addr));
|
||||
@@ -152,7 +152,7 @@ namespace
|
||||
throw std::runtime_error("Unsupported host address family for conversion: " + std::to_string(a.get_family()));
|
||||
}
|
||||
|
||||
network::address convert_to_host_address(const std::span<const std::byte> data)
|
||||
network::address convert_to_host_address(const windows_emulator& win_emu, const std::span<const std::byte> data)
|
||||
{
|
||||
if (data.size() < sizeof(win_sockaddr))
|
||||
{
|
||||
@@ -177,7 +177,7 @@ namespace
|
||||
memcpy(&win_addr4, data.data(), sizeof(win_addr4));
|
||||
|
||||
a.set_ipv4(win_addr4.sin_addr);
|
||||
a.set_port(ntohs(win_addr4.sin_port));
|
||||
a.set_port(win_emu.get_host_port(ntohs(win_addr4.sin_port)));
|
||||
|
||||
return a;
|
||||
}
|
||||
@@ -534,7 +534,7 @@ namespace
|
||||
return STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
const auto addr = convert_to_host_address(std::span(data).subspan(address_offset));
|
||||
const auto addr = convert_to_host_address(win_emu, std::span(data).subspan(address_offset));
|
||||
|
||||
if (bind(*this->s_, &addr.get_addr(), addr.get_size()) == SOCKET_ERROR)
|
||||
{
|
||||
@@ -645,7 +645,7 @@ namespace
|
||||
const auto data_size = std::min(data.size(), static_cast<size_t>(recevied_data));
|
||||
emu.write_memory(buffer.buf, data.data(), data_size);
|
||||
|
||||
const auto win_from = convert_to_win_address(from);
|
||||
const auto win_from = convert_to_win_address(win_emu, from);
|
||||
|
||||
if (receive_info.Address && receive_info.AddressLength)
|
||||
{
|
||||
@@ -681,7 +681,7 @@ namespace
|
||||
auto address_buffer = emu.read_memory(send_info.TdiConnInfo.RemoteAddress,
|
||||
static_cast<size_t>(send_info.TdiConnInfo.RemoteAddressLength));
|
||||
|
||||
const auto target = convert_to_host_address(address_buffer);
|
||||
const auto target = convert_to_host_address(win_emu, address_buffer);
|
||||
const auto data = emu.read_memory(buffer.buf, buffer.len);
|
||||
|
||||
const auto sent_data =
|
||||
|
||||
@@ -19,6 +19,12 @@ class file_system
|
||||
? win_path
|
||||
: (this->working_dir_ / win_path);
|
||||
|
||||
const auto mapping = this->mappings_.find(full_path);
|
||||
if (mapping != this->mappings_.end())
|
||||
{
|
||||
return mapping->second;
|
||||
}
|
||||
|
||||
#ifdef OS_WINDOWS
|
||||
if (this->root_.empty())
|
||||
{
|
||||
@@ -85,7 +91,13 @@ class file_system
|
||||
buffer.read(this->working_dir_);
|
||||
}
|
||||
|
||||
void map(windows_path src, std::filesystem::path dest)
|
||||
{
|
||||
this->mappings_[std::move(src)] = std::move(dest);
|
||||
}
|
||||
|
||||
private:
|
||||
std::filesystem::path root_{};
|
||||
windows_path working_dir_{};
|
||||
std::unordered_map<windows_path, std::filesystem::path> mappings_{};
|
||||
};
|
||||
|
||||
@@ -838,6 +838,16 @@ windows_emulator::windows_emulator(const emulator_settings& settings, emulator_c
|
||||
this->file_sys().set_working_directory(settings.application.parent());
|
||||
}
|
||||
|
||||
for (const auto& mapping : settings.path_mappings)
|
||||
{
|
||||
this->file_sys().map(mapping.first, mapping.second);
|
||||
}
|
||||
|
||||
for (const auto& mapping : settings.port_mappings)
|
||||
{
|
||||
this->map_port(mapping.first, mapping.second);
|
||||
}
|
||||
|
||||
this->verbose_calls = settings.verbose_calls;
|
||||
this->silent_until_main_ = settings.silent_until_main && !settings.disable_logging;
|
||||
this->use_relative_time_ = settings.use_relative_time;
|
||||
|
||||
@@ -36,6 +36,8 @@ struct emulator_settings
|
||||
bool disable_logging{false};
|
||||
bool silent_until_main{false};
|
||||
bool use_relative_time{false};
|
||||
std::unordered_map<uint16_t, uint16_t> port_mappings{};
|
||||
std::unordered_map<windows_path, std::filesystem::path> path_mappings{};
|
||||
};
|
||||
|
||||
enum class apiset_location : uint8_t
|
||||
@@ -114,6 +116,45 @@ class windows_emulator
|
||||
this->syscall_hooks_.push_back(std::move(callback));
|
||||
}
|
||||
|
||||
uint16_t get_host_port(const uint16_t emulator_port) const
|
||||
{
|
||||
const auto entry = this->port_mappings_.find(emulator_port);
|
||||
if (entry == this->port_mappings_.end())
|
||||
{
|
||||
return emulator_port;
|
||||
}
|
||||
|
||||
return entry->second;
|
||||
}
|
||||
|
||||
uint16_t get_emulator_port(const uint16_t host_port) const
|
||||
{
|
||||
for (const auto& mapping : this->port_mappings_)
|
||||
{
|
||||
if (mapping.second == host_port)
|
||||
{
|
||||
return mapping.first;
|
||||
}
|
||||
}
|
||||
|
||||
return host_port;
|
||||
}
|
||||
|
||||
void map_port(const uint16_t emulator_port, const uint16_t host_port)
|
||||
{
|
||||
if (emulator_port != host_port)
|
||||
{
|
||||
this->port_mappings_[emulator_port] = host_port;
|
||||
return;
|
||||
}
|
||||
|
||||
const auto entry = this->port_mappings_.find(emulator_port);
|
||||
if (entry != this->port_mappings_.end())
|
||||
{
|
||||
this->port_mappings_.erase(entry);
|
||||
}
|
||||
}
|
||||
|
||||
logger log{};
|
||||
bool verbose{false};
|
||||
bool verbose_calls{false};
|
||||
@@ -161,6 +202,7 @@ class windows_emulator
|
||||
|
||||
std::unique_ptr<x64_emulator> emu_{};
|
||||
std::vector<instruction_hook_callback> syscall_hooks_{};
|
||||
std::unordered_map<uint16_t, uint16_t> port_mappings_{};
|
||||
|
||||
process_context process_;
|
||||
syscall_dispatcher dispatcher_;
|
||||
|
||||
@@ -30,6 +30,8 @@ namespace windows_path_detail
|
||||
class windows_path
|
||||
{
|
||||
public:
|
||||
friend std::hash<windows_path>;
|
||||
|
||||
windows_path() = default;
|
||||
|
||||
windows_path(const std::filesystem::path& path)
|
||||
@@ -234,3 +236,24 @@ class windows_path
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct std::hash<windows_path>
|
||||
{
|
||||
std::size_t operator()(const windows_path& k) const noexcept
|
||||
{
|
||||
auto hash = std::hash<bool>()(k.drive_.has_value());
|
||||
|
||||
if (k.drive_.has_value())
|
||||
{
|
||||
hash ^= std::hash<char>()(*k.drive_);
|
||||
}
|
||||
|
||||
for (const auto& folder : k.folders_)
|
||||
{
|
||||
hash ^= std::hash<std::u16string>()(folder);
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user