backend-infra-engineer: Release v0.3.2 snapshot

This commit is contained in:
scawful
2025-10-17 12:10:25 -04:00
parent 4371618a9b
commit 3d71417f62
857 changed files with 174954 additions and 45626 deletions

View File

@@ -0,0 +1,93 @@
#include "cli/service/resources/resource_catalog.h"
#include <algorithm>
#include <string>
#include "gtest/gtest.h"
namespace yaze {
namespace cli {
namespace {
TEST(ResourceCatalogTest, SerializeResourceIncludesReturnsArray) {
const auto& catalog = ResourceCatalog::Instance();
auto overworld_schema = catalog.GetResource("overworld");
ASSERT_TRUE(overworld_schema.ok());
std::string output = catalog.SerializeResource(overworld_schema.value());
EXPECT_NE(output.find("\"resources\""), std::string::npos);
EXPECT_NE(output.find("\"returns\":"), std::string::npos);
EXPECT_NE(output.find("\"tile\""), std::string::npos);
}
TEST(ResourceCatalogTest, SerializeAllResourcesIncludesAgentDescribeMetadata) {
const auto& catalog = ResourceCatalog::Instance();
std::string output = catalog.SerializeResources(catalog.AllResources());
EXPECT_NE(output.find("\"agent\""), std::string::npos);
EXPECT_NE(output.find("\"effects\":"), std::string::npos);
EXPECT_NE(output.find("\"returns\":"), std::string::npos);
}
TEST(ResourceCatalogTest, RomSchemaExposesActionsAndMetadata) {
const auto& catalog = ResourceCatalog::Instance();
auto rom_schema = catalog.GetResource("rom");
ASSERT_TRUE(rom_schema.ok());
const auto& actions = rom_schema->actions;
ASSERT_EQ(actions.size(), 3);
EXPECT_EQ(actions[0].name, "validate");
EXPECT_FALSE(actions[0].effects.empty());
EXPECT_FALSE(actions[0].returns.empty());
EXPECT_EQ(actions[1].name, "diff");
EXPECT_EQ(actions[2].name, "generate-golden");
}
TEST(ResourceCatalogTest, PatchSchemaIncludesAsarAndCreateActions) {
const auto& catalog = ResourceCatalog::Instance();
auto patch_schema = catalog.GetResource("patch");
ASSERT_TRUE(patch_schema.ok());
const auto& actions = patch_schema->actions;
ASSERT_GE(actions.size(), 3);
EXPECT_EQ(actions[0].name, "apply");
EXPECT_FALSE(actions[0].returns.empty());
auto has_asar = std::find_if(actions.begin(), actions.end(), [](const auto& action) {
return action.name == "apply-asar";
});
EXPECT_NE(has_asar, actions.end());
auto has_create = std::find_if(actions.begin(), actions.end(), [](const auto& action) {
return action.name == "create";
});
EXPECT_NE(has_create, actions.end());
}
TEST(ResourceCatalogTest, DungeonSchemaListsMetadataAndObjectsReturns) {
const auto& catalog = ResourceCatalog::Instance();
auto dungeon_schema = catalog.GetResource("dungeon");
ASSERT_TRUE(dungeon_schema.ok());
const auto& actions = dungeon_schema->actions;
ASSERT_EQ(actions.size(), 2);
EXPECT_EQ(actions[0].name, "export");
EXPECT_FALSE(actions[0].returns.empty());
EXPECT_EQ(actions[1].name, "list-objects");
EXPECT_FALSE(actions[1].returns.empty());
}
TEST(ResourceCatalogTest, YamlSerializationIncludesMetadataAndActions) {
const auto& catalog = ResourceCatalog::Instance();
std::string yaml = catalog.SerializeResourcesAsYaml(
catalog.AllResources(), "0.1.0", "2025-10-01");
EXPECT_NE(yaml.find("version: \"0.1.0\""), std::string::npos);
EXPECT_NE(yaml.find("name: \"patch\""), std::string::npos);
EXPECT_NE(yaml.find("effects:"), std::string::npos);
EXPECT_NE(yaml.find("returns:"), std::string::npos);
}
} // namespace
} // namespace cli
} // namespace yaze

View File

@@ -0,0 +1,244 @@
// Test suite for Tile16ProposalGenerator
// Tests the new ParseSetAreaCommand and ParseReplaceTileCommand functionality
#include "cli/service/planning/tile16_proposal_generator.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
#include "app/rom.h"
#include "test/mocks/mock_rom.h"
namespace yaze {
namespace cli {
namespace {
using ::testing::_;
using ::testing::Return;
class Tile16ProposalGeneratorTest : public ::testing::Test {
protected:
void SetUp() override {
generator_ = std::make_unique<Tile16ProposalGenerator>();
}
std::unique_ptr<Tile16ProposalGenerator> generator_;
};
// ============================================================================
// ParseSetTileCommand Tests
// ============================================================================
TEST_F(Tile16ProposalGeneratorTest, ParseSetTileCommand_ValidCommand) {
std::string command = "overworld set-tile --map 0 --x 10 --y 20 --tile 0x02E";
auto result = generator_->ParseSetTileCommand(command, nullptr);
ASSERT_TRUE(result.ok()) << result.status().message();
EXPECT_EQ(result->map_id, 0);
EXPECT_EQ(result->x, 10);
EXPECT_EQ(result->y, 20);
EXPECT_EQ(result->new_tile, 0x02E);
}
TEST_F(Tile16ProposalGeneratorTest, ParseSetTileCommand_InvalidFormat) {
std::string command = "overworld set-tile --map 0"; // Missing required args
auto result = generator_->ParseSetTileCommand(command, nullptr);
EXPECT_FALSE(result.ok());
EXPECT_THAT(result.status().message(),
::testing::HasSubstr("Invalid command format"));
}
TEST_F(Tile16ProposalGeneratorTest, ParseSetTileCommand_WrongCommandType) {
std::string command = "overworld get-tile --map 0 --x 10 --y 20";
auto result = generator_->ParseSetTileCommand(command, nullptr);
EXPECT_FALSE(result.ok());
EXPECT_THAT(result.status().message(),
::testing::HasSubstr("Not a set-tile command"));
}
// ============================================================================
// ParseSetAreaCommand Tests
// ============================================================================
TEST_F(Tile16ProposalGeneratorTest, ParseSetAreaCommand_ValidCommand) {
std::string command =
"overworld set-area --map 0 --x 10 --y 20 --width 5 --height 3 --tile 0x02E";
auto result = generator_->ParseSetAreaCommand(command, nullptr);
ASSERT_TRUE(result.ok()) << result.status().message();
EXPECT_EQ(result->size(), 15); // 5 width * 3 height = 15 tiles
// Check first tile
EXPECT_EQ((*result)[0].map_id, 0);
EXPECT_EQ((*result)[0].x, 10);
EXPECT_EQ((*result)[0].y, 20);
EXPECT_EQ((*result)[0].new_tile, 0x02E);
// Check last tile
EXPECT_EQ((*result)[14].x, 14); // 10 + 4
EXPECT_EQ((*result)[14].y, 22); // 20 + 2
}
TEST_F(Tile16ProposalGeneratorTest, ParseSetAreaCommand_SingleTile) {
std::string command =
"overworld set-area --map 0 --x 10 --y 20 --width 1 --height 1 --tile 0x02E";
auto result = generator_->ParseSetAreaCommand(command, nullptr);
ASSERT_TRUE(result.ok());
EXPECT_EQ(result->size(), 1);
}
TEST_F(Tile16ProposalGeneratorTest, ParseSetAreaCommand_LargeArea) {
std::string command =
"overworld set-area --map 0 --x 0 --y 0 --width 32 --height 32 --tile 0x000";
auto result = generator_->ParseSetAreaCommand(command, nullptr);
ASSERT_TRUE(result.ok());
EXPECT_EQ(result->size(), 1024); // 32 * 32
}
TEST_F(Tile16ProposalGeneratorTest, ParseSetAreaCommand_InvalidFormat) {
std::string command = "overworld set-area --map 0 --x 10"; // Missing args
auto result = generator_->ParseSetAreaCommand(command, nullptr);
EXPECT_FALSE(result.ok());
EXPECT_THAT(result.status().message(),
::testing::HasSubstr("Invalid set-area command format"));
}
// ============================================================================
// ParseReplaceTileCommand Tests
// ============================================================================
TEST_F(Tile16ProposalGeneratorTest, ParseReplaceTileCommand_NoROM) {
std::string command =
"overworld replace-tile --map 0 --old-tile 0x02E --new-tile 0x030";
auto result = generator_->ParseReplaceTileCommand(command, nullptr);
EXPECT_FALSE(result.ok());
EXPECT_THAT(result.status().message(),
::testing::HasSubstr("ROM must be loaded"));
}
TEST_F(Tile16ProposalGeneratorTest, ParseReplaceTileCommand_InvalidFormat) {
std::string command = "overworld replace-tile --map 0"; // Missing tiles
auto result = generator_->ParseReplaceTileCommand(command, nullptr);
EXPECT_FALSE(result.ok());
EXPECT_THAT(result.status().message(),
::testing::HasSubstr("Invalid replace-tile command format"));
}
// ============================================================================
// GenerateFromCommands Tests
// ============================================================================
TEST_F(Tile16ProposalGeneratorTest, GenerateFromCommands_MultipleCommands) {
std::vector<std::string> commands = {
"overworld set-tile --map 0 --x 10 --y 20 --tile 0x02E",
"overworld set-area --map 0 --x 5 --y 5 --width 2 --height 2 --tile 0x030"
};
auto result = generator_->GenerateFromCommands(
"Test prompt", commands, "test_ai", nullptr);
ASSERT_TRUE(result.ok()) << result.status().message();
EXPECT_EQ(result->changes.size(), 5); // 1 from set-tile + 4 from set-area
EXPECT_EQ(result->prompt, "Test prompt");
EXPECT_EQ(result->ai_service, "test_ai");
EXPECT_EQ(result->status, Tile16Proposal::Status::PENDING);
}
TEST_F(Tile16ProposalGeneratorTest, GenerateFromCommands_EmptyCommands) {
std::vector<std::string> commands = {};
auto result = generator_->GenerateFromCommands(
"Test prompt", commands, "test_ai", nullptr);
EXPECT_FALSE(result.ok());
EXPECT_THAT(result.status().message(),
::testing::HasSubstr("No valid tile16 changes found"));
}
TEST_F(Tile16ProposalGeneratorTest, GenerateFromCommands_IgnoresComments) {
std::vector<std::string> commands = {
"# This is a comment",
"overworld set-tile --map 0 --x 10 --y 20 --tile 0x02E",
"# Another comment",
"" // Empty line
};
auto result = generator_->GenerateFromCommands(
"Test prompt", commands, "test_ai", nullptr);
ASSERT_TRUE(result.ok());
EXPECT_EQ(result->changes.size(), 1); // Only the valid command
}
// ============================================================================
// Tile16Change Tests
// ============================================================================
TEST_F(Tile16ProposalGeneratorTest, Tile16Change_ToString) {
Tile16Change change;
change.map_id = 5;
change.x = 10;
change.y = 20;
change.old_tile = 0x02E;
change.new_tile = 0x030;
std::string result = change.ToString();
EXPECT_THAT(result, ::testing::HasSubstr("Map 5"));
EXPECT_THAT(result, ::testing::HasSubstr("(10,20)"));
EXPECT_THAT(result, ::testing::HasSubstr("0x2e"));
EXPECT_THAT(result, ::testing::HasSubstr("0x30"));
}
// ============================================================================
// Proposal Serialization Tests
// ============================================================================
TEST_F(Tile16ProposalGeneratorTest, Proposal_ToJsonAndFromJson) {
Tile16Proposal original;
original.id = "test_id_123";
original.prompt = "Test prompt";
original.ai_service = "gemini";
original.reasoning = "Test reasoning";
original.status = Tile16Proposal::Status::PENDING;
Tile16Change change;
change.map_id = 5;
change.x = 10;
change.y = 20;
change.old_tile = 0x02E;
change.new_tile = 0x030;
original.changes.push_back(change);
std::string json = original.ToJson();
auto result = Tile16Proposal::FromJson(json);
ASSERT_TRUE(result.ok()) << result.status().message();
EXPECT_EQ(result->id, original.id);
EXPECT_EQ(result->prompt, original.prompt);
EXPECT_EQ(result->ai_service, original.ai_service);
EXPECT_EQ(result->reasoning, original.reasoning);
EXPECT_EQ(result->status, original.status);
EXPECT_EQ(result->changes.size(), 1);
EXPECT_EQ(result->changes[0].map_id, 5);
}
} // namespace
} // namespace cli
} // namespace yaze