import Testing @testable import PureXML /// The standalone validity constraints (2.9) and the standalone entity WFC: /// a document declaring standalone='yes' must not depend on declarations in /// the external subset. @Suite("Standalone validity") struct DTDStandaloneTests { private let externalDTD = """ """ private func resolver() -> PureXML.Parsing.EntityResolver { let dtd = externalDTD return PureXML.Parsing.EntityResolver( resolveEntity: { _, _ in nil }, resolveExternalSubset: { _ in dtd }, ) } private func errors(_ xml: String) throws -> [String] { try PureXML.validateAgainstInternalDTD(xml, resolver: resolver()).map(\.reason) } @Test("An externally-declared default firing is a standalone violation") func test_externalDefault() throws { let xml = "\n\n" #expect(try errors(xml).contains { $0.contains("externally-declared default") }) // standalone='no' is fine. let declared = "\n\n" #expect(try !errors(declared).contains { $0.contains("externally-declared") }) } @Test("External normalization needed is a standalone violation, supplied values are fine") func test_externalNormalization() throws { let needs = "\n\n" #expect(try errors(needs).contains { $0.contains("externally-declared normalization") }) let clean = "\n\n" #expect(try !errors(clean).contains { $0.contains("normalization") }) } @Test("Whitespace in externally-declared element content is a standalone violation") func test_externalElementWhitespace() throws { let xml = "\n\n\n x\n" #expect(try errors(xml).contains { $0.contains("whitespace in the externally-declared element content") }) } @Test("Internally-declared attributes do not trip the standalone rules") func test_internalDeclarationsExempt() throws { let xml = """ ]> """ // token is internally redeclared (first wins), so its default and // normalization are internal facts; only external facts may fire. #expect(try !errors(xml).contains { $0.contains("'token'") }) } @Test("A standalone document may not reference an externally-declared entity") func test_standaloneEntityWFC() { let xml = "\n\n&outside;" #expect(throws: PureXML.Parsing.ParseError.self) { _ = try PureXML.parse(xml, limits: .init(allowDoctype: true), resolver: resolver()) } // Without standalone the reference resolves. let loose = "\n&outside;" #expect((try? PureXML.parse(loose, limits: .init(allowDoctype: true), resolver: resolver())) != nil) } }