backend-infra-engineer: Release v0.3.3 snapshot
This commit is contained in:
@@ -1,13 +1,12 @@
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#include "absl/strings/str_format.h"
|
||||
#include "cli/service/ai/ai_action_parser.h"
|
||||
#include "cli/service/ai/vision_action_refiner.h"
|
||||
#include "cli/service/ai/ai_gui_controller.h"
|
||||
#include "cli/service/ai/vision_action_refiner.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
#ifdef YAZE_WITH_GRPC
|
||||
#include "cli/service/gui/gui_automation_client.h"
|
||||
#include "cli/service/ai/gemini_ai_service.h"
|
||||
#include "cli/service/gui/gui_automation_client.h"
|
||||
#endif
|
||||
|
||||
namespace yaze {
|
||||
@@ -15,7 +14,7 @@ namespace test {
|
||||
|
||||
/**
|
||||
* @brief Integration tests for AI-controlled tile placement
|
||||
*
|
||||
*
|
||||
* These tests verify the complete pipeline:
|
||||
* 1. Parse natural language commands
|
||||
* 2. Execute actions via gRPC
|
||||
@@ -32,33 +31,33 @@ class AITilePlacementTest : public ::testing::Test {
|
||||
|
||||
TEST_F(AITilePlacementTest, ParsePlaceTileCommand) {
|
||||
using namespace cli::ai;
|
||||
|
||||
|
||||
// Test basic tile placement command
|
||||
auto result = AIActionParser::ParseCommand(
|
||||
"Place tile 0x42 at overworld position (5, 7)");
|
||||
|
||||
|
||||
ASSERT_TRUE(result.ok()) << result.status().message();
|
||||
EXPECT_EQ(result->size(), 3); // Select, Place, Save
|
||||
|
||||
|
||||
// Check first action (Select)
|
||||
EXPECT_EQ(result->at(0).type, AIActionType::kSelectTile);
|
||||
EXPECT_EQ(result->at(0).parameters.at("tile_id"), "66"); // 0x42 = 66
|
||||
|
||||
|
||||
// Check second action (Place)
|
||||
EXPECT_EQ(result->at(1).type, AIActionType::kPlaceTile);
|
||||
EXPECT_EQ(result->at(1).parameters.at("x"), "5");
|
||||
EXPECT_EQ(result->at(1).parameters.at("y"), "7");
|
||||
EXPECT_EQ(result->at(1).parameters.at("map_id"), "0");
|
||||
|
||||
|
||||
// Check third action (Save)
|
||||
EXPECT_EQ(result->at(2).type, AIActionType::kSaveTile);
|
||||
}
|
||||
|
||||
TEST_F(AITilePlacementTest, ParseSelectTileCommand) {
|
||||
using namespace cli::ai;
|
||||
|
||||
|
||||
auto result = AIActionParser::ParseCommand("Select tile 100");
|
||||
|
||||
|
||||
ASSERT_TRUE(result.ok());
|
||||
EXPECT_EQ(result->size(), 1);
|
||||
EXPECT_EQ(result->at(0).type, AIActionType::kSelectTile);
|
||||
@@ -67,9 +66,9 @@ TEST_F(AITilePlacementTest, ParseSelectTileCommand) {
|
||||
|
||||
TEST_F(AITilePlacementTest, ParseOpenEditorCommand) {
|
||||
using namespace cli::ai;
|
||||
|
||||
|
||||
auto result = AIActionParser::ParseCommand("Open the overworld editor");
|
||||
|
||||
|
||||
ASSERT_TRUE(result.ok());
|
||||
EXPECT_EQ(result->size(), 1);
|
||||
EXPECT_EQ(result->at(0).type, AIActionType::kOpenEditor);
|
||||
@@ -78,13 +77,10 @@ TEST_F(AITilePlacementTest, ParseOpenEditorCommand) {
|
||||
|
||||
TEST_F(AITilePlacementTest, ActionToStringRoundtrip) {
|
||||
using namespace cli::ai;
|
||||
|
||||
AIAction action(AIActionType::kPlaceTile, {
|
||||
{"x", "5"},
|
||||
{"y", "7"},
|
||||
{"tile_id", "42"}
|
||||
});
|
||||
|
||||
|
||||
AIAction action(AIActionType::kPlaceTile,
|
||||
{{"x", "5"}, {"y", "7"}, {"tile_id", "42"}});
|
||||
|
||||
std::string str = AIActionParser::ActionToString(action);
|
||||
EXPECT_FALSE(str.empty());
|
||||
EXPECT_TRUE(str.find("5") != std::string::npos);
|
||||
@@ -99,14 +95,14 @@ TEST_F(AITilePlacementTest, DISABLED_VisionAnalysisBasic) {
|
||||
if (!api_key || std::string(api_key).empty()) {
|
||||
GTEST_SKIP() << "GEMINI_API_KEY not set";
|
||||
}
|
||||
|
||||
|
||||
cli::GeminiConfig config;
|
||||
config.api_key = api_key;
|
||||
config.model = "gemini-2.5-flash";
|
||||
|
||||
|
||||
cli::GeminiAIService gemini_service(config);
|
||||
cli::ai::VisionActionRefiner refiner(&gemini_service);
|
||||
|
||||
|
||||
// Would need actual screenshots for real test
|
||||
// This is a structure test
|
||||
EXPECT_TRUE(true);
|
||||
@@ -117,35 +113,35 @@ TEST_F(AITilePlacementTest, DISABLED_FullAIControlLoop) {
|
||||
// 1. YAZE GUI running with gRPC test harness
|
||||
// 2. Gemini API key for vision
|
||||
// 3. Test ROM loaded
|
||||
|
||||
|
||||
const char* api_key = std::getenv("GEMINI_API_KEY");
|
||||
if (!api_key || std::string(api_key).empty()) {
|
||||
GTEST_SKIP() << "GEMINI_API_KEY not set";
|
||||
}
|
||||
|
||||
|
||||
// Initialize services
|
||||
cli::GeminiConfig gemini_config;
|
||||
gemini_config.api_key = api_key;
|
||||
cli::GeminiAIService gemini_service(gemini_config);
|
||||
|
||||
|
||||
cli::GuiAutomationClient gui_client("localhost:50051");
|
||||
auto connect_status = gui_client.Connect();
|
||||
if (!connect_status.ok()) {
|
||||
GTEST_SKIP() << "GUI test harness not available: "
|
||||
GTEST_SKIP() << "GUI test harness not available: "
|
||||
<< connect_status.message();
|
||||
}
|
||||
|
||||
|
||||
// Create AI controller
|
||||
cli::ai::AIGUIController controller(&gemini_service, &gui_client);
|
||||
cli::ai::ControlLoopConfig config;
|
||||
config.max_iterations = 5;
|
||||
config.enable_vision_verification = true;
|
||||
controller.Initialize(config);
|
||||
|
||||
|
||||
// Execute command
|
||||
auto result = controller.ExecuteCommand(
|
||||
"Place tile 0x42 at overworld position (5, 7)");
|
||||
|
||||
auto result =
|
||||
controller.ExecuteCommand("Place tile 0x42 at overworld position (5, 7)");
|
||||
|
||||
if (result.ok()) {
|
||||
EXPECT_TRUE(result->success);
|
||||
EXPECT_GT(result->iterations_performed, 0);
|
||||
@@ -156,16 +152,14 @@ TEST_F(AITilePlacementTest, DISABLED_FullAIControlLoop) {
|
||||
|
||||
TEST_F(AITilePlacementTest, ActionRefinement) {
|
||||
using namespace cli::ai;
|
||||
|
||||
|
||||
// Test refinement logic with a failed action
|
||||
VisionAnalysisResult analysis;
|
||||
analysis.action_successful = false;
|
||||
analysis.error_message = "Element not found";
|
||||
|
||||
AIAction original_action(AIActionType::kClickButton, {
|
||||
{"button", "save"}
|
||||
});
|
||||
|
||||
|
||||
AIAction original_action(AIActionType::kClickButton, {{"button", "save"}});
|
||||
|
||||
// Would need VisionActionRefiner for real test
|
||||
// This verifies the structure compiles
|
||||
EXPECT_TRUE(true);
|
||||
@@ -173,15 +167,12 @@ TEST_F(AITilePlacementTest, ActionRefinement) {
|
||||
|
||||
TEST_F(AITilePlacementTest, MultipleCommandsParsing) {
|
||||
using namespace cli::ai;
|
||||
|
||||
|
||||
// Test that we can parse multiple commands in sequence
|
||||
std::vector<std::string> commands = {
|
||||
"Open overworld editor",
|
||||
"Select tile 0x42",
|
||||
"Place tile at position (5, 7)",
|
||||
"Save changes"
|
||||
};
|
||||
|
||||
"Open overworld editor", "Select tile 0x42",
|
||||
"Place tile at position (5, 7)", "Save changes"};
|
||||
|
||||
for (const auto& cmd : commands) {
|
||||
auto result = AIActionParser::ParseCommand(cmd);
|
||||
// At least some should parse successfully
|
||||
@@ -193,13 +184,13 @@ TEST_F(AITilePlacementTest, MultipleCommandsParsing) {
|
||||
|
||||
TEST_F(AITilePlacementTest, HexAndDecimalParsing) {
|
||||
using namespace cli::ai;
|
||||
|
||||
|
||||
// Test hex notation
|
||||
auto hex_result = AIActionParser::ParseCommand("Select tile 0xFF");
|
||||
if (hex_result.ok() && !hex_result->empty()) {
|
||||
EXPECT_EQ(hex_result->at(0).parameters.at("tile_id"), "255");
|
||||
}
|
||||
|
||||
|
||||
// Test decimal notation
|
||||
auto dec_result = AIActionParser::ParseCommand("Select tile 255");
|
||||
if (dec_result.ok() && !dec_result->empty()) {
|
||||
|
||||
Reference in New Issue
Block a user