import Testing @testable import PureXML /// Encoding-declaration contradictions are fatal (#137, 4.3.3): a declared /// 16/32-bit encoding over 8-bit bytes, a declaration outside the BOM's /// family, and an external entity declaring a version above the document's /// (errata E38). @Suite("Encoding declaration mismatches") struct EncodingMismatchTests { @Test("UTF-16 declared over 8-bit bytes is rejected") func test_wideOverNarrow() { let bytes = Array("\n\n".utf8) #expect(throws: PureXML.Parsing.ParseError.self) { _ = try PureXML.Parsing.ByteDecoder.decode(bytes) } } @Test("A declaration outside the BOM's family is rejected") func test_bomContradiction() { // UTF-8 BOM + iso-8859-1 declaration. let utf8: [UInt8] = [0xEF, 0xBB, 0xBF] + Array("".utf8) #expect(throws: PureXML.Parsing.ParseError.self) { _ = try PureXML.Parsing.ByteDecoder.decode(utf8) } // UTF-16BE BOM + iso-8859-1 declaration. var utf16: [UInt8] = [0xFE, 0xFF] for scalar in "".unicodeScalars { utf16.append(0) utf16.append(UInt8(scalar.value)) } #expect(throws: PureXML.Parsing.ParseError.self) { _ = try PureXML.Parsing.ByteDecoder.decode(utf16) } // Matching declarations stay accepted. let consistent: [UInt8] = [0xEF, 0xBB, 0xBF] + Array("".utf8) #expect((try? PureXML.Parsing.ByteDecoder.decode(consistent)) != nil) } @Test("An external entity declaring a higher version is rejected (E38)") func test_entityVersionAboveDocument() { let xml = "]>\n&e;" let resolver = PureXML.Parsing.EntityResolver( resolveEntity: { _, _ in "ok" }, resolveExternalSubset: { _ in nil }, ) #expect(throws: PureXML.Parsing.ParseError.self) { _ = try PureXML.parse(xml, limits: .init(allowDoctype: true), resolver: resolver) } let sameVersion = PureXML.Parsing.EntityResolver( resolveEntity: { _, _ in "ok" }, resolveExternalSubset: { _ in nil }, ) #expect((try? PureXML.parse(xml, limits: .init(allowDoctype: true), resolver: sameVersion)) != nil) } }