#include #include #include #include #include #include #include namespace { using XCEngine::UI::UIRect; using XCEngine::UI::Runtime::UIScreenAsset; using XCEngine::UI::Runtime::UIScreenFrameInput; using XCEngine::UI::Runtime::UIScreenPlayer; using XCEngine::UI::Runtime::UIDocumentScreenHost; namespace fs = std::filesystem; class TempFileScope { public: TempFileScope(std::string stem, std::string extension, std::string contents) { const auto uniqueId = std::to_string( std::chrono::steady_clock::now().time_since_epoch().count()); m_path = fs::temp_directory_path() / (std::move(stem) + "_" + uniqueId + std::move(extension)); std::ofstream output(m_path, std::ios::binary | std::ios::trunc); output << contents; } ~TempFileScope() { std::error_code ec; fs::remove(m_path, ec); } const fs::path& Path() const { return m_path; } private: fs::path m_path = {}; }; UIScreenAsset BuildScreenAsset(const fs::path& viewPath, const char* screenId) { UIScreenAsset screen = {}; screen.screenId = screenId; screen.documentPath = viewPath.string(); return screen; } UIScreenFrameInput BuildInputState(std::uint64_t frameIndex = 1u) { UIScreenFrameInput input = {}; input.viewportRect = UIRect(0.0f, 0.0f, 960.0f, 720.0f); input.frameIndex = frameIndex; input.focused = true; return input; } } // namespace TEST(UIRuntimeSplitterValidationTest, InvalidSplitterArityProducesExplicitFrameError) { TempFileScope viewFile( "xcui_runtime_invalid_splitter", ".xcui", "\n" " \n" " \n" " \n" " \n" " \n" "\n"); UIDocumentScreenHost host = {}; UIScreenPlayer player(host); ASSERT_TRUE(player.Load(BuildScreenAsset(viewFile.Path(), "runtime.invalid_splitter"))); const auto& frame = player.Update(BuildInputState()); EXPECT_FALSE(frame.errorMessage.empty()); EXPECT_NE(frame.errorMessage.find("broken-splitter"), std::string::npos); EXPECT_NE(frame.errorMessage.find("exactly 2 child elements"), std::string::npos); }