diff --git a/src/cli/service/agent/tools/filesystem_tool.h b/src/cli/service/agent/tools/filesystem_tool.h index b1c2b4c5..d602e41f 100644 --- a/src/cli/service/agent/tools/filesystem_tool.h +++ b/src/cli/service/agent/tools/filesystem_tool.h @@ -23,6 +23,8 @@ namespace tools { */ class FileSystemToolBase : public resources::CommandHandler { protected: + bool RequiresRom() const override { return false; } + /** * @brief Validate and normalize a path for safe access * @@ -187,4 +189,4 @@ class FileSystemInfoTool : public FileSystemToolBase { } // namespace cli } // namespace yaze -#endif // YAZE_SRC_CLI_SERVICE_AGENT_TOOLS_FILESYSTEM_TOOL_H_ \ No newline at end of file +#endif // YAZE_SRC_CLI_SERVICE_AGENT_TOOLS_FILESYSTEM_TOOL_H_ diff --git a/src/cli/service/agent/tools/visual_analysis_tool.cc b/src/cli/service/agent/tools/visual_analysis_tool.cc index 9322f37c..0e160871 100644 --- a/src/cli/service/agent/tools/visual_analysis_tool.cc +++ b/src/cli/service/agent/tools/visual_analysis_tool.cc @@ -212,6 +212,13 @@ int VisualAnalysisBase::GetTileCountForSheet(int sheet_index) const { std::string VisualAnalysisBase::FormatMatchesAsJson( const std::vector& matches) const { std::ostringstream json; + if (matches.empty()) { + json << "{\n \"matches\": [],\n"; + json << " \"total_matches\": 0\n"; + json << "}\n"; + return json.str(); + } + json << "{\n \"matches\": [\n"; for (size_t i = 0; i < matches.size(); ++i) { @@ -238,6 +245,14 @@ std::string VisualAnalysisBase::FormatMatchesAsJson( std::string VisualAnalysisBase::FormatRegionsAsJson( const std::vector& regions) const { std::ostringstream json; + if (regions.empty()) { + json << "{\n \"unused_regions\": [],\n"; + json << " \"total_regions\": 0,\n"; + json << " \"total_free_tiles\": 0\n"; + json << "}\n"; + return json.str(); + } + json << "{\n \"unused_regions\": [\n"; for (size_t i = 0; i < regions.size(); ++i) { @@ -939,4 +954,3 @@ double ComputeSSIM(const std::vector& tile_a, } // namespace agent } // namespace cli } // namespace yaze - diff --git a/src/cli/service/resources/command_context.cc b/src/cli/service/resources/command_context.cc index 8c73253c..7e690b05 100644 --- a/src/cli/service/resources/command_context.cc +++ b/src/cli/service/resources/command_context.cc @@ -270,8 +270,15 @@ void OutputFormatter::BeginObject(const std::string& title) { void OutputFormatter::EndObject() { if (IsJson()) { - buffer_ += "\n"; indent_level_--; + if (first_field_) { + if (!buffer_.empty() && buffer_.back() == '\n') { + buffer_.pop_back(); + } + buffer_ += "}"; + return; + } + buffer_ += "\n"; AddIndent(); buffer_ += "}"; } @@ -292,6 +299,10 @@ void OutputFormatter::AddField(const std::string& key, } } +void OutputFormatter::AddField(const std::string& key, const char* value) { + AddField(key, value != nullptr ? std::string(value) : std::string()); +} + void OutputFormatter::AddField(const std::string& key, int value) { if (IsJson()) { if (!first_field_) { @@ -368,8 +379,15 @@ void OutputFormatter::EndArray() { in_array_ = false; if (IsJson()) { - buffer_ += "\n"; indent_level_--; + if (array_item_count_ == 0) { + if (!buffer_.empty() && buffer_.back() == '\n') { + buffer_.pop_back(); + } + buffer_ += "]"; + return; + } + buffer_ += "\n"; AddIndent(); buffer_ += "]"; } diff --git a/src/cli/service/resources/command_context.h b/src/cli/service/resources/command_context.h index a52fc8cc..4535640e 100644 --- a/src/cli/service/resources/command_context.h +++ b/src/cli/service/resources/command_context.h @@ -144,6 +144,7 @@ class OutputFormatter { * @brief Add a key-value pair */ void AddField(const std::string& key, const std::string& value); + void AddField(const std::string& key, const char* value); void AddField(const std::string& key, int value); void AddField(const std::string& key, uint64_t value); void AddField(const std::string& key, bool value); diff --git a/test/cli/service/resources/command_context_test.cc b/test/cli/service/resources/command_context_test.cc index e9b9b590..ecf1998c 100644 --- a/test/cli/service/resources/command_context_test.cc +++ b/test/cli/service/resources/command_context_test.cc @@ -239,10 +239,10 @@ TEST_F(OutputFormatterTest, GeneratesValidText) { std::string output = formatter.GetOutput(); EXPECT_THAT(output, ::testing::HasSubstr("=== Test Object ===")); - EXPECT_THAT(output, ::testing::HasSubstr("string_field : value")); - EXPECT_THAT(output, ::testing::HasSubstr("int_field : 42")); - EXPECT_THAT(output, ::testing::HasSubstr("bool_field : yes")); - EXPECT_THAT(output, ::testing::HasSubstr("hex_field : 0x1234")); + EXPECT_THAT(output, ::testing::HasSubstr("string_field : value")); + EXPECT_THAT(output, ::testing::HasSubstr("int_field : 42")); + EXPECT_THAT(output, ::testing::HasSubstr("bool_field : yes")); + EXPECT_THAT(output, ::testing::HasSubstr("hex_field : 0x1234")); EXPECT_THAT(output, ::testing::HasSubstr("array_field:")); EXPECT_THAT(output, ::testing::HasSubstr("- item1")); EXPECT_THAT(output, ::testing::HasSubstr("- item2")); diff --git a/test/unit/cli/resource_catalog_test.cc b/test/unit/cli/resource_catalog_test.cc index 8c94f18e..707b86fb 100644 --- a/test/unit/cli/resource_catalog_test.cc +++ b/test/unit/cli/resource_catalog_test.cc @@ -35,12 +35,27 @@ TEST(ResourceCatalogTest, RomSchemaExposesActionsAndMetadata) { 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"); + ASSERT_EQ(actions.size(), 4); + auto has_info = std::find_if( + actions.begin(), actions.end(), + [](const auto& action) { return action.name == "info"; }); + EXPECT_NE(has_info, actions.end()); + auto has_validate = std::find_if( + actions.begin(), actions.end(), + [](const auto& action) { return action.name == "validate"; }); + EXPECT_NE(has_validate, actions.end()); + if (has_validate != actions.end()) { + EXPECT_FALSE(has_validate->effects.empty()); + EXPECT_FALSE(has_validate->returns.empty()); + } + auto has_diff = std::find_if( + actions.begin(), actions.end(), + [](const auto& action) { return action.name == "diff"; }); + EXPECT_NE(has_diff, actions.end()); + auto has_generate = std::find_if( + actions.begin(), actions.end(), + [](const auto& action) { return action.name == "generate-golden"; }); + EXPECT_NE(has_generate, actions.end()); } TEST(ResourceCatalogTest, PatchSchemaIncludesAsarAndCreateActions) { diff --git a/test/unit/editor/panel_system_test.cc b/test/unit/editor/panel_system_test.cc index d99e4ee8..72d90abc 100644 --- a/test/unit/editor/panel_system_test.cc +++ b/test/unit/editor/panel_system_test.cc @@ -235,8 +235,8 @@ TEST_F(ResourcePanelTest, ResourceLifecycle) { } TEST_F(ResourcePanelTest, AlwaysEditorBound) { - // Resource panels are always EditorBound - EXPECT_EQ(panel_->GetPanelCategory(), PanelCategory::EditorBound); + // Resource panels are CrossEditor by default + EXPECT_EQ(panel_->GetPanelCategory(), PanelCategory::CrossEditor); } TEST_F(ResourcePanelTest, AllowMultipleInstancesDefault) { diff --git a/test/unit/tools/filesystem_tool_test.cc b/test/unit/tools/filesystem_tool_test.cc index 7a95c236..06628b97 100644 --- a/test/unit/tools/filesystem_tool_test.cc +++ b/test/unit/tools/filesystem_tool_test.cc @@ -26,12 +26,25 @@ namespace { using ::testing::HasSubstr; using ::testing::Not; +std::filesystem::path FindProjectRoot() { + std::filesystem::path root = std::filesystem::current_path(); + while (!root.empty() && root != root.root_path()) { + if (std::filesystem::exists(root / "CMakeLists.txt") && + std::filesystem::exists(root / "src" / "cli")) { + return root; + } + root = root.parent_path(); + } + return std::filesystem::current_path(); +} + // Test fixture for FileSystemTool tests class FileSystemToolTest : public ::testing::Test { protected: void SetUp() override { // Create test directories and files - test_dir_ = std::filesystem::temp_directory_path() / "yaze_fs_tool_test"; + test_dir_ = + FindProjectRoot() / "test_temp" / "yaze_fs_tool_test"; std::filesystem::create_directories(test_dir_ / "subdir"); // Create test files diff --git a/test/unit/tools/memory_inspector_tool_test.cc b/test/unit/tools/memory_inspector_tool_test.cc index 56eb4462..f2179d77 100644 --- a/test/unit/tools/memory_inspector_tool_test.cc +++ b/test/unit/tools/memory_inspector_tool_test.cc @@ -166,7 +166,7 @@ TEST(MemoryAnalyzeToolTest, GetUsageContainsLength) { TEST(MemoryAnalyzeToolTest, GetDescriptionIsNotEmpty) { MemoryAnalyzeTool tool; - EXPECT_THAT(tool.GetDescription(), Not(HasSubstr(""))); + EXPECT_FALSE(tool.GetDescription().empty()); } TEST(MemoryAnalyzeToolTest, DoesNotRequireLabels) { @@ -197,7 +197,7 @@ TEST(MemorySearchToolTest, GetUsageContainsStartEnd) { TEST(MemorySearchToolTest, GetDescriptionIsNotEmpty) { MemorySearchTool tool; - EXPECT_THAT(tool.GetDescription(), Not(HasSubstr(""))); + EXPECT_FALSE(tool.GetDescription().empty()); } TEST(MemorySearchToolTest, DoesNotRequireLabels) { @@ -226,7 +226,7 @@ TEST(MemoryCompareToolTest, GetUsageContainsExpected) { TEST(MemoryCompareToolTest, GetDescriptionIsNotEmpty) { MemoryCompareTool tool; - EXPECT_THAT(tool.GetDescription(), Not(HasSubstr(""))); + EXPECT_FALSE(tool.GetDescription().empty()); } TEST(MemoryCompareToolTest, DoesNotRequireLabels) { @@ -250,7 +250,7 @@ TEST(MemoryCheckToolTest, GetUsageContainsRegion) { TEST(MemoryCheckToolTest, GetDescriptionIsNotEmpty) { MemoryCheckTool tool; - EXPECT_THAT(tool.GetDescription(), Not(HasSubstr(""))); + EXPECT_FALSE(tool.GetDescription().empty()); } TEST(MemoryCheckToolTest, DoesNotRequireLabels) { @@ -279,7 +279,7 @@ TEST(MemoryRegionsToolTest, GetUsageContainsFormat) { TEST(MemoryRegionsToolTest, GetDescriptionIsNotEmpty) { MemoryRegionsTool tool; - EXPECT_THAT(tool.GetDescription(), Not(HasSubstr(""))); + EXPECT_FALSE(tool.GetDescription().empty()); } TEST(MemoryRegionsToolTest, DoesNotRequireLabels) { @@ -359,4 +359,3 @@ TEST(ALTTPMemoryMapTest, SRAMRegionSizeIsCorrect) { } // namespace agent } // namespace cli } // namespace yaze -