import Testing @testable import PureXML /// A redefinition of an attribute group restricts the original (src-redefine), so /// it may neither eliminate a required attribute nor re-introduce a prohibited one /// as usable. Keeping a required attribute, and re-declaring a prohibited attribute /// as prohibited, are both valid (W3C attgZ002/attgZ003, schT3). @Suite("redefined attribute group restriction") struct SchemaRedefineAttributeGroupTests { private func redefine(group body: String, base: String) throws -> PureXML.Schema.Document { let main = "" + "\(body)" + "" let baseDoc = "" + "\(base)" return try PureXML.Schema.Document(main, schemaLoader: { _ in baseDoc }) } @Test("eliminating a required attribute is rejected") func test_dropRequiredRejected() throws { #expect(throws: (any Error).self) { try redefine( group: "", base: "", ) } } @Test("re-introducing a prohibited attribute as usable is rejected") func test_reintroduceProhibitedRejected() throws { #expect(throws: (any Error).self) { try redefine( group: "", base: "", ) } } @Test("keeping a required attribute and re-prohibiting a prohibited one is valid") func test_validRedefinitionAccepted() throws { _ = try redefine( group: "", base: "", ) } @Test("relaxing a fixed value in the redefinition is rejected") func test_relaxFixedRejected() throws { #expect(throws: (any Error).self) { try redefine( group: "", base: "", ) } } @Test("keeping the same fixed value in the redefinition is valid") func test_keepFixedAccepted() throws { _ = try redefine( group: "", base: "", ) } @Test("adding an attribute not in the original is rejected (superset)") func test_addAttributeRejected() throws { #expect(throws: (any Error).self) { try redefine( group: "", base: "", ) } } @Test("declaring a prohibited attribute the base lacks is valid (not a superset)") func test_addProhibitedAccepted() throws { _ = try redefine( group: "", base: "", ) } @Test("re-declaring an attribute the self-reference already supplies is rejected (schM8)") func test_selfRefRedeclareDuplicateRejected() throws { // The self-reference re-imports the original's `a`, so directly re-declaring `a` // produces two attribute uses of the same name: a duplicate (ag-props-correct.2). #expect(throws: (any Error).self) { try redefine( group: "", base: "", ) } } @Test("a self-reference re-declaring a prohibited attribute is not flagged as duplicate (lenient)") func test_selfRefRedeclareProhibitedLenient() throws { // A `use="prohibited"` re-declaration removes rather than duplicates, so the // duplicate check declines; the base attribute is optional, so this compiles. _ = try redefine( group: "", base: "", ) } @Test("adding an attribute alongside a self-reference is valid") func test_addWithSelfReferenceAccepted() throws { _ = try redefine( group: "", base: "", ) } @Test("a duplicate attribute via a redefined self-referencing group is rejected (attQ011)") func test_redefineSelfRefDuplicateAcrossReferences() throws { // attG references the global `foo` AND the redefined `red`; `red` self-references, // so its original (which declares `foo`) is re-imported. attG then holds two // attribute uses named `foo`: a duplicate (ag-props-correct.2). let main = "" + "" + "" + "" + "" + "" + "" let baseDoc = "" + "" #expect(throws: (any Error).self) { try PureXML.Schema.Document(main, schemaLoader: { _ in baseDoc }) } } @Test("a redefined self-referencing group supplying a distinct attribute is valid (no false duplicate)") func test_redefineSelfRefDistinctAttributeAccepted() throws { // Same shape, but `red`'s original declares `bar`, not `foo`: attG holds `foo` // and `bar`, no duplicate, so the self-reference expansion must not over-flag. let main = "" + "" + "" + "" + "" + "" + "" let baseDoc = "" + "" _ = try PureXML.Schema.Document(main, schemaLoader: { _ in baseDoc }) } @Test("widening a re-declared attribute's built-in type is rejected (schM4)") func test_widenBuiltinTypeRejected() throws { // int does not derive by restriction from boolean, so re-typing the attribute // from boolean to int widens it: a redefinition must restrict, not widen. #expect(throws: (any Error).self) { try redefine( group: "", base: "", ) } } @Test("narrowing a re-declared attribute's built-in type within the lattice is valid") func test_narrowBuiltinTypeAccepted() throws { // int derives from integer, so re-typing integer -> int is a valid restriction. _ = try redefine( group: "", base: "", ) } @Test("re-typing an originally untyped attribute is valid (anySimpleType base)") func test_retypeUntypedBaseAccepted() throws { // An absent base type is anySimpleType, which any type validly restricts. _ = try redefine( group: "", base: "", ) } @Test("a user type whose local name coincides with a built-in is not mistaken for it (no false positive)") func test_userTypeNamedLikeBuiltinNotWidened() throws { // The redefinition re-types `a` to `tns:int`, a USER simpleType that restricts // xs:string. Its local name is the built-in keyword `int`, but it resolves to // the target namespace, not the XSD namespace, so the type-widening check must // not treat it as xsd:int (which would not derive from xsd:string) and reject. let main = "" + "" + "" + "" + "" let baseDoc = "" + "" _ = try PureXML.Schema.Document(main, schemaLoader: { _ in baseDoc }) } @Test("a non-self reference injecting a foreign attribute is rejected (attgC028)") func test_nonSelfReferenceAddRejected() throws { let main = "" + "" + "" + "" + "" + "" let baseDoc = "" + "" #expect(throws: (any Error).self) { try PureXML.Schema.Document(main, schemaLoader: { _ in baseDoc }) } } @Test("a non-self reference whose attributes are all in the original is valid") func test_nonSelfReferenceSubsetAccepted() throws { let main = "" + "" + "" + "" + "" let baseDoc = "" + "" + "" _ = try PureXML.Schema.Document(main, schemaLoader: { _ in baseDoc }) } @Test("a referenced group with an attribute wildcard is not judged (lenient, no false positive)") func test_nonSelfReferenceWildcardLenient() throws { let main = "" + "" + "" + "" + "" + "" let baseDoc = "" + "" _ = try PureXML.Schema.Document(main, schemaLoader: { _ in baseDoc }) } @Test("re-declaring an attribute the base inherits via a reference is valid") func test_redeclareInheritedAccepted() throws { let main = "" + "" + "" + "" let baseDoc = "" + "" + "" _ = try PureXML.Schema.Document(main, schemaLoader: { _ in baseDoc }) } }