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) }
}
}