Add XCUI schema document regression coverage

This commit is contained in:
2026-04-05 05:45:51 +08:00
parent 6dcf881967
commit a7662a1d43
7 changed files with 278 additions and 7 deletions

View File

@@ -0,0 +1,153 @@
#include <gtest/gtest.h>
#include <XCEngine/Resources/UI/UIDocumentCompiler.h>
#include <XCEngine/Resources/UI/UIDocumentLoaders.h>
#include <filesystem>
#include <fstream>
using namespace XCEngine::Resources;
namespace {
void WriteTextFile(const std::filesystem::path& path, const std::string& contents) {
std::filesystem::create_directories(path.parent_path());
std::ofstream output(path, std::ios::binary | std::ios::trunc);
ASSERT_TRUE(output.is_open());
output << contents;
ASSERT_TRUE(static_cast<bool>(output));
}
TEST(UISchemaDocument, CompileAndArtifactLoadPopulateSchemaDefinition) {
namespace fs = std::filesystem;
const fs::path root = fs::temp_directory_path() / "xc_ui_schema_compile_test";
const fs::path schemaPath = root / "markup.xcschema";
const fs::path artifactPath = root / "markup.xcschemaasset";
fs::remove_all(root);
WriteTextFile(
schemaPath,
"<Schema name=\"EditorMarkup\">\n"
" <Element tag=\"View\" allowUnknownChildren=\"true\">\n"
" <Attribute name=\"theme\" type=\"document\" kind=\"theme\" />\n"
" <Attribute name=\"mode\" type=\"enum\" values=\"compact, cozy\" />\n"
" <Element tag=\"Column\">\n"
" <Attribute name=\"gap\" type=\"number\" />\n"
" </Element>\n"
" </Element>\n"
"</Schema>\n");
UISchemaLoader loader;
UIDocumentCompileResult compileResult = {};
ASSERT_TRUE(loader.CompileDocument(schemaPath.string().c_str(), compileResult));
ASSERT_TRUE(compileResult.succeeded);
ASSERT_TRUE(compileResult.document.valid);
ASSERT_TRUE(compileResult.document.schemaDefinition.valid);
EXPECT_EQ(compileResult.document.schemaDefinition.name, "EditorMarkup");
const UISchemaElementDefinition* viewElement =
compileResult.document.schemaDefinition.FindElement("View");
ASSERT_NE(viewElement, nullptr);
EXPECT_TRUE(viewElement->allowUnknownChildren);
const UISchemaAttributeDefinition* themeAttribute = viewElement->FindAttribute("theme");
ASSERT_NE(themeAttribute, nullptr);
EXPECT_EQ(themeAttribute->valueType, UISchemaValueType::Document);
EXPECT_TRUE(themeAttribute->restrictDocumentKind);
EXPECT_EQ(themeAttribute->documentKind, UIDocumentKind::Theme);
const UISchemaAttributeDefinition* modeAttribute = viewElement->FindAttribute("mode");
ASSERT_NE(modeAttribute, nullptr);
EXPECT_EQ(modeAttribute->valueType, UISchemaValueType::Enum);
ASSERT_EQ(modeAttribute->allowedValues.Size(), 2u);
EXPECT_EQ(modeAttribute->allowedValues[0], "compact");
EXPECT_EQ(modeAttribute->allowedValues[1], "cozy");
LoadResult loadResult = loader.Load(schemaPath.string().c_str());
ASSERT_TRUE(loadResult);
ASSERT_NE(loadResult.resource, nullptr);
auto* schemaResource = static_cast<UISchema*>(loadResult.resource);
ASSERT_NE(schemaResource, nullptr);
ASSERT_TRUE(schemaResource->GetSchemaDefinition().valid);
ASSERT_NE(schemaResource->GetSchemaDefinition().FindElement("View"), nullptr);
delete schemaResource;
XCEngine::Containers::String artifactWriteError;
ASSERT_TRUE(
WriteUIDocumentArtifact(artifactPath.string().c_str(), compileResult, &artifactWriteError))
<< artifactWriteError.CStr();
UIDocumentCompileResult artifactResult = {};
ASSERT_TRUE(LoadUIDocumentArtifact(
artifactPath.string().c_str(),
UIDocumentKind::Schema,
artifactResult));
ASSERT_TRUE(artifactResult.succeeded);
ASSERT_TRUE(artifactResult.document.valid);
ASSERT_TRUE(artifactResult.document.schemaDefinition.valid);
const UISchemaElementDefinition* artifactViewElement =
artifactResult.document.schemaDefinition.FindElement("View");
ASSERT_NE(artifactViewElement, nullptr);
ASSERT_NE(artifactViewElement->FindChild("Column"), nullptr);
fs::remove_all(root);
}
TEST(UISchemaDocument, CompileRejectsInvalidSchemaFlags) {
namespace fs = std::filesystem;
const fs::path root = fs::temp_directory_path() / "xc_ui_schema_invalid_flag_test";
const fs::path schemaPath = root / "broken.xcschema";
fs::remove_all(root);
WriteTextFile(
schemaPath,
"<Schema>\n"
" <Element tag=\"View\" allowUnknownChildren=\"sometimes\" />\n"
"</Schema>\n");
UISchemaLoader loader;
UIDocumentCompileResult compileResult = {};
EXPECT_FALSE(loader.CompileDocument(schemaPath.string().c_str(), compileResult));
EXPECT_FALSE(compileResult.succeeded);
EXPECT_FALSE(compileResult.errorMessage.Empty());
ASSERT_FALSE(compileResult.document.diagnostics.Empty());
const std::string errorMessage = compileResult.errorMessage.CStr();
EXPECT_NE(errorMessage.find("allowUnknownChildren"), std::string::npos);
fs::remove_all(root);
}
TEST(UISchemaDocument, CompileRejectsDuplicateAttributeDefinitions) {
namespace fs = std::filesystem;
const fs::path root = fs::temp_directory_path() / "xc_ui_schema_duplicate_attribute_test";
const fs::path schemaPath = root / "duplicate.xcschema";
fs::remove_all(root);
WriteTextFile(
schemaPath,
"<Schema>\n"
" <Element tag=\"View\">\n"
" <Attribute name=\"id\" type=\"string\" />\n"
" <Attribute name=\"id\" type=\"string\" />\n"
" </Element>\n"
"</Schema>\n");
UISchemaLoader loader;
UIDocumentCompileResult compileResult = {};
EXPECT_FALSE(loader.CompileDocument(schemaPath.string().c_str(), compileResult));
EXPECT_FALSE(compileResult.succeeded);
EXPECT_FALSE(compileResult.errorMessage.Empty());
ASSERT_FALSE(compileResult.document.diagnostics.Empty());
const std::string errorMessage = compileResult.errorMessage.CStr();
EXPECT_NE(errorMessage.find("Duplicate schema attribute definition"), std::string::npos);
fs::remove_all(root);
}
} // namespace