feat: Enhance ImGuiTestHarnessServer with proper shutdown handling and update gRPC service initialization
This commit is contained in:
@@ -208,6 +208,10 @@ ImGuiTestHarnessServer& ImGuiTestHarnessServer::Instance() {
|
||||
return *instance;
|
||||
}
|
||||
|
||||
ImGuiTestHarnessServer::~ImGuiTestHarnessServer() {
|
||||
Shutdown();
|
||||
}
|
||||
|
||||
absl::Status ImGuiTestHarnessServer::Start(int port) {
|
||||
if (server_) {
|
||||
return absl::FailedPreconditionError("Server already running");
|
||||
@@ -216,19 +220,19 @@ absl::Status ImGuiTestHarnessServer::Start(int port) {
|
||||
// Create the service implementation
|
||||
service_ = std::make_unique<ImGuiTestHarnessServiceImpl>();
|
||||
|
||||
// Create the gRPC service wrapper
|
||||
auto grpc_service = std::make_unique<ImGuiTestHarnessServiceGrpc>(service_.get());
|
||||
// Create the gRPC service wrapper (store as member to prevent it from going out of scope)
|
||||
grpc_service_ = std::make_unique<ImGuiTestHarnessServiceGrpc>(service_.get());
|
||||
|
||||
std::string server_address = absl::StrFormat("127.0.0.1:%d", port);
|
||||
std::string server_address = absl::StrFormat("0.0.0.0:%d", port);
|
||||
|
||||
grpc::ServerBuilder builder;
|
||||
|
||||
// Listen on localhost only (security)
|
||||
// Listen on all interfaces (use 0.0.0.0 to avoid IPv6/IPv4 binding conflicts)
|
||||
builder.AddListeningPort(server_address,
|
||||
grpc::InsecureServerCredentials());
|
||||
|
||||
// Register service
|
||||
builder.RegisterService(grpc_service.get());
|
||||
builder.RegisterService(grpc_service_.get());
|
||||
|
||||
// Build and start
|
||||
server_ = builder.BuildAndStart();
|
||||
|
||||
@@ -68,6 +68,9 @@ class ImGuiTestHarnessServiceImpl {
|
||||
ScreenshotResponse* response);
|
||||
};
|
||||
|
||||
// Forward declaration of the gRPC service wrapper
|
||||
class ImGuiTestHarnessServiceGrpc;
|
||||
|
||||
// Singleton server managing the gRPC service
|
||||
// This class manages the lifecycle of the gRPC server
|
||||
class ImGuiTestHarnessServer {
|
||||
@@ -91,7 +94,7 @@ class ImGuiTestHarnessServer {
|
||||
|
||||
private:
|
||||
ImGuiTestHarnessServer() = default;
|
||||
~ImGuiTestHarnessServer() { Shutdown(); }
|
||||
~ImGuiTestHarnessServer(); // Defined in .cc file to allow incomplete type deletion
|
||||
|
||||
// Disable copy and move
|
||||
ImGuiTestHarnessServer(const ImGuiTestHarnessServer&) = delete;
|
||||
@@ -99,6 +102,7 @@ class ImGuiTestHarnessServer {
|
||||
|
||||
std::unique_ptr<grpc::Server> server_;
|
||||
std::unique_ptr<ImGuiTestHarnessServiceImpl> service_;
|
||||
std::unique_ptr<ImGuiTestHarnessServiceGrpc> grpc_service_;
|
||||
int port_ = 0;
|
||||
};
|
||||
|
||||
|
||||
@@ -9,6 +9,10 @@
|
||||
#include "util/flag.h"
|
||||
#include "util/log.h"
|
||||
|
||||
#ifdef YAZE_WITH_GRPC
|
||||
#include "app/core/imgui_test_harness_service.h"
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @namespace yaze
|
||||
* @brief Main namespace for the application.
|
||||
@@ -20,6 +24,14 @@ DEFINE_FLAG(std::string, rom_file, "", "The ROM file to load.");
|
||||
DEFINE_FLAG(std::string, log_file, "", "Output log file path for debugging.");
|
||||
DEFINE_FLAG(bool, debug, false, "Enable debug logging and verbose output.");
|
||||
|
||||
#ifdef YAZE_WITH_GRPC
|
||||
// gRPC test harness flags
|
||||
DEFINE_FLAG(bool, enable_test_harness, false,
|
||||
"Start gRPC test harness server for automated GUI testing.");
|
||||
DEFINE_FLAG(int, test_harness_port, 50051,
|
||||
"Port for gRPC test harness server (default: 50051).");
|
||||
#endif
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
absl::InitializeSymbolizer(argv[0]);
|
||||
|
||||
@@ -56,6 +68,24 @@ int main(int argc, char **argv) {
|
||||
rom_filename = FLAGS_rom_file->Get();
|
||||
}
|
||||
|
||||
#ifdef YAZE_WITH_GRPC
|
||||
// Start gRPC test harness server if requested
|
||||
if (FLAGS_enable_test_harness->Get()) {
|
||||
auto& server = yaze::test::ImGuiTestHarnessServer::Instance();
|
||||
int port = FLAGS_test_harness_port->Get();
|
||||
|
||||
std::cout << "\n🚀 Starting ImGui Test Harness on port " << port << "..." << std::endl;
|
||||
auto status = server.Start(port);
|
||||
if (!status.ok()) {
|
||||
std::cerr << "❌ ERROR: Failed to start test harness server on port " << port << std::endl;
|
||||
std::cerr << " " << status.message() << std::endl;
|
||||
return 1;
|
||||
}
|
||||
std::cout << "✅ Test harness ready on 127.0.0.1:" << port << std::endl;
|
||||
std::cout << " Available RPCs: Ping, Click, Type, Wait, Assert, Screenshot\n" << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
return yaze_run_cocoa_app_delegate(rom_filename.c_str());
|
||||
#elif defined(_WIN32)
|
||||
@@ -76,5 +106,10 @@ int main(int argc, char **argv) {
|
||||
}
|
||||
controller->OnExit();
|
||||
|
||||
#ifdef YAZE_WITH_GRPC
|
||||
// Shutdown gRPC server if running
|
||||
yaze::test::ImGuiTestHarnessServer::Instance().Shutdown();
|
||||
#endif
|
||||
|
||||
return EXIT_SUCCESS;
|
||||
}
|
||||
|
||||
@@ -48,6 +48,9 @@ class Flag : public IFlag {
|
||||
}
|
||||
value_ = parsed;
|
||||
}
|
||||
|
||||
// Set the value directly (used by specializations)
|
||||
void SetValue(const T& val) { value_ = val; }
|
||||
|
||||
// Returns the current (parsed or default) value of the flag.
|
||||
const T& Get() const { return value_; }
|
||||
@@ -59,6 +62,19 @@ class Flag : public IFlag {
|
||||
std::string help_;
|
||||
};
|
||||
|
||||
// Specialization for bool to handle "true"/"false" strings
|
||||
template <>
|
||||
inline void Flag<bool>::ParseValue(const std::string& text) {
|
||||
if (text == "true" || text == "1" || text == "yes" || text == "on") {
|
||||
SetValue(true);
|
||||
} else if (text == "false" || text == "0" || text == "no" || text == "off") {
|
||||
SetValue(false);
|
||||
} else {
|
||||
throw std::runtime_error("Failed to parse boolean flag: " + name() +
|
||||
" (expected true/false/1/0/yes/no/on/off, got: " + text + ")");
|
||||
}
|
||||
}
|
||||
|
||||
class FlagRegistry {
|
||||
public:
|
||||
// Registers a flag in the global registry.
|
||||
|
||||
Reference in New Issue
Block a user