diff --git a/src/windows-emulator-test/emulation_test_utils.hpp b/src/windows-emulator-test/emulation_test_utils.hpp index f874329..c45db02 100644 --- a/src/windows-emulator-test/emulation_test_utils.hpp +++ b/src/windows-emulator-test/emulation_test_utils.hpp @@ -5,14 +5,14 @@ #define ASSERT_NOT_TERMINATED(win_emu) \ do { \ - ASSERT_FALSE(win_emu.process().exit_status.has_value()); \ + ASSERT_FALSE((win_emu).process().exit_status.has_value()); \ } while(false) #define ASSERT_TERMINATED_WITH_STATUS(win_emu, status) \ do { \ - ASSERT_TRUE(win_emu.process().exit_status.has_value()); \ - ASSERT_EQ(*win_emu.process().exit_status, status); \ + ASSERT_TRUE((win_emu).process().exit_status.has_value()); \ + ASSERT_EQ(*(win_emu).process().exit_status, status); \ } while(false) #define ASSERT_TERMINATED_SUCCESSFULLY(win_emu) \ @@ -20,15 +20,20 @@ namespace test { + inline windows_emulator create_sample_emulator(emulator_settings& settings) + { + settings.application = "./test-sample.exe"; + return windows_emulator{settings}; + } + inline windows_emulator create_sample_emulator() { - const emulator_settings settings + emulator_settings settings { - .application = "./test-sample.exe", .disable_logging = true, .use_relative_time = true, }; - return windows_emulator{settings}; + return create_sample_emulator(settings); } } diff --git a/src/windows-emulator-test/time_test.cpp b/src/windows-emulator-test/time_test.cpp new file mode 100644 index 0000000..6e11420 --- /dev/null +++ b/src/windows-emulator-test/time_test.cpp @@ -0,0 +1,45 @@ +#include "emulation_test_utils.hpp" + +namespace test +{ + TEST(TimeTest, SystemTimeIsAccurate) + { + std::string output_buffer{}; + + emulator_settings settings{ + .arguments = {L"-time"}, + .stdout_callback = [&output_buffer](const std::string_view data) + { + output_buffer.append(data); + }, + .disable_logging = true, + .use_relative_time = false, + }; + + auto emu = create_sample_emulator(settings); + emu.start(); + + constexpr auto prefix = "Time: "sv; + + ASSERT_TERMINATED_SUCCESSFULLY(emu); + ASSERT_TRUE(output_buffer.starts_with(prefix)); + + output_buffer = output_buffer.substr(prefix.size()); + while (!output_buffer.empty() && (output_buffer.back() == '\n' || output_buffer.back() == '\r')) + { + output_buffer.pop_back(); + } + + const auto time = strtoll(output_buffer.c_str(), nullptr, 10); + + using time_point = std::chrono::system_clock::time_point; + + const time_point::duration time_duration(time); + const time_point tp(time_duration); + + const auto now = std::chrono::system_clock::now(); + const auto diff = now - tp; + + ASSERT_LE(diff, std::chrono::hours(1)); + } +} diff --git a/src/windows-emulator/syscalls.cpp b/src/windows-emulator/syscalls.cpp index bac61fe..dd977b9 100644 --- a/src/windows-emulator/syscalls.cpp +++ b/src/windows-emulator/syscalls.cpp @@ -1985,6 +1985,7 @@ namespace temp_buffer.push_back('\n'); } + c.win_emu.on_stdout(temp_buffer); c.win_emu.logger.info("%.*s", static_cast(temp_buffer.size()), temp_buffer.data()); return STATUS_SUCCESS; diff --git a/src/windows-emulator/windows_emulator.cpp b/src/windows-emulator/windows_emulator.cpp index 2e0ff39..fa8ef0c 100644 --- a/src/windows-emulator/windows_emulator.cpp +++ b/src/windows-emulator/windows_emulator.cpp @@ -690,6 +690,7 @@ windows_emulator::windows_emulator(const emulator_settings& settings, std::unique_ptr emu) : windows_emulator(std::move(emu)) { + this->stdout_callback_ = std::move(settings.stdout_callback); this->use_relative_time_ = settings.use_relative_time; this->logger.disable_output(settings.disable_logging); this->setup_process(settings); diff --git a/src/windows-emulator/windows_emulator.hpp b/src/windows-emulator/windows_emulator.hpp index 23bce87..a31f39f 100644 --- a/src/windows-emulator/windows_emulator.hpp +++ b/src/windows-emulator/windows_emulator.hpp @@ -9,12 +9,14 @@ std::unique_ptr create_default_x64_emulator(); +// TODO: Split up into application and emulator settings struct emulator_settings { std::filesystem::path application{}; std::filesystem::path working_directory{}; std::filesystem::path registry_directory{"./registry"}; std::vector arguments{}; + std::function stdout_callback{}; bool disable_logging{false}; bool use_relative_time{false}; }; @@ -86,6 +88,14 @@ class windows_emulator this->syscall_hooks_.push_back(std::move(callback)); } + void on_stdout(const std::string_view data) const + { + if (this->stdout_callback_) + { + this->stdout_callback_(data); + } + } + logger logger{}; bool verbose{false}; bool verbose_calls{false}; @@ -105,7 +115,7 @@ class windows_emulator bool use_relative_time_{false}; std::unique_ptr emu_{}; std::vector syscall_hooks_{}; - + std::function stdout_callback_{}; process_context process_; syscall_dispatcher dispatcher_;