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