mirror of
https://github.com/momo5502/emulator.git
synced 2026-01-10 16:16:16 +00:00
Prepare unittest support
This commit is contained in:
3
.gitmodules
vendored
3
.gitmodules
vendored
@@ -15,3 +15,6 @@
|
||||
path = deps/mini-gdbstub
|
||||
url = ../mini-gdbstub.git
|
||||
shallow = true
|
||||
[submodule "deps/googletest"]
|
||||
path = deps/googletest
|
||||
url = https://github.com/google/googletest.git
|
||||
|
||||
3
deps/CMakeLists.txt
vendored
3
deps/CMakeLists.txt
vendored
@@ -12,4 +12,5 @@ target_include_directories(reflect INTERFACE
|
||||
|
||||
##########################################
|
||||
|
||||
include(mini-gdbstub.cmake)
|
||||
include(mini-gdbstub.cmake)
|
||||
include(googletest.cmake)
|
||||
1
deps/googletest
vendored
Submodule
1
deps/googletest
vendored
Submodule
Submodule deps/googletest added at df1544bcee
4
deps/googletest.cmake
vendored
Normal file
4
deps/googletest.cmake
vendored
Normal file
@@ -0,0 +1,4 @@
|
||||
option(BUILD_GMOCK OFF)
|
||||
option(INSTALL_GTEST OFF)
|
||||
|
||||
add_subdirectory(googletest)
|
||||
@@ -7,3 +7,4 @@ add_subdirectory(fuzzing-engine)
|
||||
add_subdirectory(fuzzer)
|
||||
add_subdirectory(bad-sample)
|
||||
add_subdirectory(test-sample)
|
||||
add_subdirectory(windows-emulator-test)
|
||||
|
||||
@@ -87,12 +87,12 @@ bool test_io()
|
||||
return text == buffer;
|
||||
}
|
||||
|
||||
#define RUN_TEST(func, name) \
|
||||
{ \
|
||||
#define RUN_TEST(func, name) \
|
||||
{ \
|
||||
printf("Running test '" name "': "); \
|
||||
const auto res = func(); \
|
||||
valid &= res; \
|
||||
puts(res ? "Sucess" : "Fail"); \
|
||||
const auto res = func(); \
|
||||
valid &= res; \
|
||||
puts(res ? "Sucess" : "Fail"); \
|
||||
}
|
||||
|
||||
int main(int /*argc*/, const char* /*argv*/[])
|
||||
|
||||
19
src/windows-emulator-test/CMakeLists.txt
Normal file
19
src/windows-emulator-test/CMakeLists.txt
Normal file
@@ -0,0 +1,19 @@
|
||||
file(GLOB_RECURSE SRC_FILES CONFIGURE_DEPENDS
|
||||
*.cpp
|
||||
*.hpp
|
||||
*.rc
|
||||
)
|
||||
|
||||
list(SORT SRC_FILES)
|
||||
|
||||
add_executable(windows-emulator-test ${SRC_FILES})
|
||||
|
||||
momo_assign_source_group(${SRC_FILES})
|
||||
|
||||
target_link_libraries(windows-emulator-test PRIVATE
|
||||
gtest
|
||||
common
|
||||
windows-emulator
|
||||
)
|
||||
|
||||
add_dependencies(windows-emulator-test test-sample)
|
||||
27
src/windows-emulator-test/emulation_test.cpp
Normal file
27
src/windows-emulator-test/emulation_test.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <windows_emulator.hpp>
|
||||
|
||||
|
||||
namespace test
|
||||
{
|
||||
TEST(EmulationTest, BasicEmulationWorks)
|
||||
{
|
||||
windows_emulator emu{"./test-sample.exe"};
|
||||
emu.logger.disable_output(true);
|
||||
emu.start();
|
||||
|
||||
ASSERT_TRUE(emu.process().exit_status.has_value());
|
||||
ASSERT_EQ(*emu.process().exit_status, 0);
|
||||
}
|
||||
|
||||
TEST(EmulationTest, CountedEmulationWorks)
|
||||
{
|
||||
constexpr auto count = 123;
|
||||
|
||||
windows_emulator emu{ "./test-sample.exe" };
|
||||
emu.logger.disable_output(true);
|
||||
emu.start({}, count);
|
||||
|
||||
ASSERT_EQ(emu.process().executed_instructions, count);
|
||||
}
|
||||
}
|
||||
7
src/windows-emulator-test/main.cpp
Normal file
7
src/windows-emulator-test/main.cpp
Normal file
@@ -0,0 +1,7 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
::testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
33
src/windows-emulator-test/serialization_test.cpp
Normal file
33
src/windows-emulator-test/serialization_test.cpp
Normal file
@@ -0,0 +1,33 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <windows_emulator.hpp>
|
||||
|
||||
|
||||
namespace test
|
||||
{
|
||||
TEST(SerializationTest, BasicSerializationWorks)
|
||||
{
|
||||
windows_emulator emu{"./test-sample.exe"};
|
||||
emu.logger.disable_output(true);
|
||||
emu.start({}, 100);
|
||||
|
||||
utils::buffer_serializer serializer{};
|
||||
emu.serialize(serializer);
|
||||
|
||||
utils::buffer_deserializer deserializer{serializer.get_buffer()};
|
||||
|
||||
windows_emulator new_emu{};
|
||||
new_emu.logger.disable_output(true);
|
||||
new_emu.deserialize(deserializer);
|
||||
|
||||
new_emu.start();
|
||||
emu.start();
|
||||
|
||||
utils::buffer_serializer serializer1{};
|
||||
utils::buffer_serializer serializer2{};
|
||||
|
||||
emu.serialize(serializer1);
|
||||
new_emu.serialize(serializer2);
|
||||
|
||||
ASSERT_EQ(serializer1.get_buffer(), serializer2.get_buffer());
|
||||
}
|
||||
}
|
||||
@@ -235,7 +235,7 @@ public:
|
||||
|
||||
std::wstring name{};
|
||||
|
||||
std::optional<uint32_t> exit_status{};
|
||||
std::optional<NTSTATUS> exit_status{};
|
||||
std::optional<handle> await_object{};
|
||||
bool waiting_for_alert{false};
|
||||
bool alerted{false};
|
||||
@@ -353,6 +353,7 @@ struct process_context
|
||||
uint64_t previous_ip{0};
|
||||
|
||||
std::optional<uint64_t> exception_rip{};
|
||||
std::optional<NTSTATUS> exit_status{};
|
||||
|
||||
emulator_allocator base_allocator;
|
||||
|
||||
@@ -390,6 +391,7 @@ struct process_context
|
||||
buffer.write(this->current_ip);
|
||||
buffer.write(this->previous_ip);
|
||||
buffer.write_optional(this->exception_rip);
|
||||
buffer.write_optional(this->exit_status);
|
||||
buffer.write(this->base_allocator);
|
||||
buffer.write(this->peb);
|
||||
buffer.write(this->process_params);
|
||||
@@ -424,6 +426,7 @@ struct process_context
|
||||
buffer.read(this->current_ip);
|
||||
buffer.read(this->previous_ip);
|
||||
buffer.read_optional(this->exception_rip);
|
||||
buffer.read_optional(this->exit_status);
|
||||
buffer.read(this->base_allocator);
|
||||
buffer.read(this->peb);
|
||||
buffer.read(this->process_params);
|
||||
|
||||
@@ -1596,15 +1596,24 @@ namespace
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtTerminateProcess(const syscall_context& c, const uint64_t process_handle,
|
||||
NTSTATUS /*exit_status*/)
|
||||
NTSTATUS exit_status)
|
||||
{
|
||||
if (process_handle == 0)
|
||||
{
|
||||
for (auto& t : c.proc.threads)
|
||||
{
|
||||
if (&t.second != c.proc.active_thread)
|
||||
{
|
||||
t.second.exit_status = exit_status;
|
||||
}
|
||||
}
|
||||
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (process_handle == ~0ULL)
|
||||
{
|
||||
c.proc.exit_status = exit_status;
|
||||
c.emu.stop();
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
@@ -2126,16 +2135,8 @@ namespace
|
||||
return STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtAlertThreadByThreadIdEx(const syscall_context& c, const uint64_t thread_id,
|
||||
const emulator_object<RTL_SRWLOCK> lock)
|
||||
NTSTATUS handle_NtAlertThreadByThreadId(const syscall_context& c, const uint64_t thread_id)
|
||||
{
|
||||
if (lock.value())
|
||||
{
|
||||
puts("NtAlertThreadByThreadIdEx with lock not supported yet!");
|
||||
//c.emu.stop();
|
||||
//return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
for (auto& t : c.proc.threads)
|
||||
{
|
||||
if (t.second.id == thread_id)
|
||||
@@ -2148,6 +2149,19 @@ namespace
|
||||
return STATUS_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtAlertThreadByThreadIdEx(const syscall_context& c, const uint64_t thread_id,
|
||||
const emulator_object<RTL_SRWLOCK> lock)
|
||||
{
|
||||
if (lock.value())
|
||||
{
|
||||
puts("NtAlertThreadByThreadIdEx with lock not supported yet!");
|
||||
//c.emu.stop();
|
||||
//return STATUS_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
return handle_NtAlertThreadByThreadId(c, thread_id);
|
||||
}
|
||||
|
||||
NTSTATUS handle_NtWaitForAlertByThreadId(const syscall_context& c, const uint64_t,
|
||||
const emulator_object<LARGE_INTEGER> timeout)
|
||||
{
|
||||
@@ -2247,6 +2261,7 @@ void syscall_dispatcher::add_handlers(std::unordered_map<std::string, syscall_ha
|
||||
add_handler(NtDelayExecution);
|
||||
add_handler(NtWaitForAlertByThreadId);
|
||||
add_handler(NtAlertThreadByThreadIdEx);
|
||||
add_handler(NtAlertThreadByThreadId);
|
||||
add_handler(NtReadFile);
|
||||
add_handler(NtSetInformationFile);
|
||||
add_handler(NtUserRegisterWindowMessage);
|
||||
|
||||
@@ -425,7 +425,7 @@ namespace
|
||||
|
||||
bool switch_to_thread(const logger& logger, x64_emulator& emu, process_context& context, emulator_thread& thread)
|
||||
{
|
||||
if (thread.exit_status.has_value() || !thread.is_thread_ready(context))
|
||||
if (!thread.is_thread_ready(context))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
@@ -584,6 +584,11 @@ void emulator_thread::mark_as_ready(const NTSTATUS status)
|
||||
|
||||
bool emulator_thread::is_thread_ready(process_context& context)
|
||||
{
|
||||
if(this->exit_status.has_value())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this->waiting_for_alert)
|
||||
{
|
||||
if (this->alerted)
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
#pragma once
|
||||
#include "std_include.hpp"
|
||||
|
||||
#include <x64_emulator.hpp>
|
||||
|
||||
#include "syscall_dispatcher.hpp"
|
||||
|
||||
Reference in New Issue
Block a user