import Testing @testable import PureXML /// The two regimes of RecurseAsIfGroup against a base choice (XSD 1.0 section /// 3.9.6): a NON-repeating choice ({max occurs} = 1) gets the literal pairing, /// a repeating choice keeps the effective-total-range reading (the particlesZ001 /// ambiguity only exists when counts accumulate across repetitions). Shapes are /// the XSTS cases that pin the boundary from both sides. @Suite("XSD element-restricts-choice: literal vs effective-range regimes") struct XSDParticleChoiceRestrictionTests { private let xsNamespace = "xmlns:xs=\"http://www.w3.org/2001/XMLSchema\"" private func schema(base: String, derived: String) -> String { """ \(base) \(derived) """ } @Test("Optional element does not restrict a required branch of a non-repeating choice") func test_ha161Rejected() { // particlesHa161: derived a{0,1} vs branch a{1,1} in choice{0,1}. Pointwise // NameAndTypeOK occurrence fails; the old effective-range reading accepted it. let source = schema( base: """ """, derived: "", ) #expect(throws: (any Error).self) { try PureXML.Schema.Document(source) } } @Test("Same-occurrence element restricting one branch of a non-repeating choice compiles") func test_ha160Accepted() throws { // particlesHa160, the settled-valid twin: a{1,1} vs branch a{1,1}. let source = schema( base: """ """, derived: "", ) _ = try PureXML.Schema.Document(source) } @Test("Element cannot map into a branch whose required sibling is unmapped") func test_m034Rejected() { // particlesM034: derived d1+ vs choice(seq(c1{2,2}, c2?), seq{1,inf}(d1*, d2+)). // Every traversal of the only d1-bearing branch emits a d2, so pure d1 content // is not in the base language; the leaf-admission reading accepted it. let source = schema( base: """ """, derived: "", ) #expect(throws: (any Error).self) { try PureXML.Schema.Document(source) } } @Test("Element maps into a branch whose other siblings are emptiable") func test_m035Accepted() throws { // particlesM035, the settled-valid twin of M034: derived d2+ maps onto the // branch's d2+ with the d1* sibling emptiable. let source = schema( base: """ """, derived: "", ) _ = try PureXML.Schema.Document(source) } @Test("Element with matching in-branch occurrence restricts a non-repeating choice") func test_m002ShapeAccepted() throws { // particlesM002: derived c1{2,2} maps into branch seq{1,3}(c1{2,2}, c2?) of a // non-repeating choice; the literal regime must keep accepting this. let source = schema( base: """ """, derived: "", ) _ = try PureXML.Schema.Document(source) } @Test("Repeating base choice keeps the effective-range reading") func test_z001ShapeAccepted() throws { // particlesZ001's shape: element{0,inf} over choice{0,inf}(...). The literal // pointwise rule would reject it; W3C reads it valid, and the repeating regime // must keep accepting counts accumulated across choice repetitions. let source = schema( base: """ """, derived: "", ) _ = try PureXML.Schema.Document(source) } @Test("Repeating base choice still bounds the effective total range") func test_ha162ShapeRejected() { // particlesHa162: a{1,3} over choice{1,2}(a|b): three a's exceed what two // traversals can produce; the repeating regime's range check rejects it. let source = schema( base: """ """, derived: "", ) #expect(throws: (any Error).self) { try PureXML.Schema.Document(source) } } }