import Testing @testable import PureXML @Suite("XSD attribute-use restriction (cos-ct-derived-ok)") struct SchemaAttributeRestrictionTests { private let xsd = "xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"" private func compiles(_ body: String) -> Bool { (try? PureXML.Schema.Document("\(body)")) != nil } private func derive(base: String, restricted: String) -> String { "\(base)" + "" + "\(restricted)" } @Test("A restriction may not relax a required attribute") func test_requiredRelaxationRejected() { let req = "" // required -> optional (explicit) #expect(!compiles(derive(base: req, restricted: ""))) // required -> optional (default use) #expect(!compiles(derive(base: req, restricted: ""))) // required -> prohibited #expect(!compiles(derive(base: req, restricted: ""))) } @Test("A faithful or tightening attribute restriction compiles") func test_validRestrictionsAccepted() { // required kept required let req = "" #expect(compiles(derive(base: req, restricted: req))) // fixed kept identical let fixed = "" #expect(compiles(derive(base: fixed, restricted: ""))) // optional base may be made prohibited or stay optional let opt = "" #expect(compiles(derive(base: opt, restricted: ""))) // an attribute the restriction does not redeclare is inherited unchanged #expect(compiles(derive(base: req, restricted: ""))) // an optional base attribute that is also fixed may be prohibited (the // prohibited use removes it, so the fixed clause does not apply). #expect(compiles(derive(base: fixed, restricted: ""))) } /// The fixed-value clause is a disclosed under-rejection (it needs value-space, /// not lexical, comparison). A list-typed fixed value that differs only in /// whitespace is the same value and must compile; and, for now, even a genuinely /// changed fixed value is accepted rather than risk a lexical false positive. @Test("Fixed-value differences on a restricted attribute: matching values compile, mismatched values are rejected") func test_fixedClauseRestrictions() { let listBase = "" + "" // Same list value, different whitespace: valid, must compile. let derivedValidWS = "" + "" #expect(compiles(listBase + derivedValidWS)) // Same integer values, different padding: valid, must compile. let intBase = "" let derivedValidInt = "" + "" #expect(compiles(intBase + derivedValidInt)) // Mismatched list values: invalid, must be rejected. let derivedInvalidList = "" + "" #expect(!compiles(listBase + derivedInvalidList)) // Mismatched integer values: invalid, must be rejected. let derivedInvalidInt = "" + "" #expect(!compiles(intBase + derivedInvalidInt)) // Missing value constraint when base is fixed: invalid, must be rejected. let derivedMissingConstraint = "" + "" #expect(!compiles(intBase + derivedMissingConstraint)) // Default value constraint when base is fixed: invalid, must be rejected. let derivedDefaultConstraint = "" + "" #expect(!compiles(intBase + derivedDefaultConstraint)) } @Test("A restriction may not change an attribute's type to a non-derived type") func test_attributeTypeRestriction() { let base = "" // integer -> string (unrelated): invalid #expect(!compiles(derive(base: base, restricted: ""))) // integer -> int (valid restriction): valid #expect(compiles(derive(base: base, restricted: ""))) // integer -> union(float, integer): invalid let unionDef = "" #expect(!compiles(unionDef + derive(base: base, restricted: ""))) } @Test("Restricting an untyped (anySimpleType) attribute to list and union types is valid") func test_anySimpleTypeRestrictedToListAndUnion() { let base = "" // untyped, defaults to xs:anySimpleType // anySimpleType -> atomic (xs:integer): valid #expect(compiles(derive(base: base, restricted: ""))) // anySimpleType -> list (xs:NMTOKENS): valid #expect(compiles(derive(base: base, restricted: ""))) // anySimpleType -> union: valid let unionDef = "" #expect(compiles(unionDef + derive(base: base, restricted: ""))) } @Test("Attributes are inherited, overridden, or prohibited correctly in complexContent restriction during instance validation") func test_attributeInheritanceAndProhibitionInInstanceValidation() throws { let schemaSource = """ """ let doc = try PureXML.Schema.Document(schemaSource) // 1. Prohibit element: a and b are inherited, c is prohibited. // - Valid instance: only has a and b. #expect(try doc.validate("").isEmpty) // - Invalid instance: has prohibited c. let invalidProhibit = try doc.validate("") #expect(!invalidProhibit.isEmpty) // 2. Override element: a is overridden to xs:int, b and c are inherited. // - Valid instance: a is an integer, b and c are strings. #expect(try doc.validate("").isEmpty) // - Invalid instance: a is not an integer. let invalidOverride = try doc.validate("") #expect(!invalidOverride.isEmpty) } @Test("Attributes in restriction with different namespaces are resolved correctly") func test_multiNamespaceAttributeRestriction() throws { let imported = """ """ let main = """ """ let loader: (String) -> String? = { $0 == "imported.xsd" ? imported : nil } let doc = try PureXML.Schema.Document(main, schemaLoader: loader) let xml = """ """ #expect(try doc.validate(xml).isEmpty) } @Test("Prohibiting an attribute defined in an attributeGroup works correctly") func test_attributeGroupProhibition() throws { let main = """ """ let doc = try PureXML.Schema.Document(main) let xml = """ """ #expect(try doc.validate(xml).isEmpty) let invalidXML = """ """ #expect(try !doc.validate(invalidXML).isEmpty) } }