@testable import PureYAML import Testing /// What a string holds is what it comes back as. The meaning of each text here is written down (YAML 1.2.2, section 5.7: an escape in a double-quoted scalar stands for /// any character, including a control character), and not taken from what the reader says of it. @Suite("String characters") struct StringCharactersTests { /// Characters that are not printable in a YAML stream and so are not written bare, with the escape that stands for each. static let escaped: [(source: String, character: String)] = [ ("\\0", "\u{0}"), ("\\x01", "\u{1}"), ("\\u0001", "\u{1}"), ("\\U00000001", "\u{1}"), ("\\x1f", "\u{1F}"), ("\\u001F", "\u{1F}"), ("\\x7f", "\u{7F}"), ("\\u007F", "\u{7F}"), ("\\x80", "\u{80}"), ("\\x9f", "\u{9F}"), ("\\N", "\u{85}"), ("\\x85", "\u{85}"), ("\\L", "\u{2028}"), ("\\u2028", "\u{2028}"), ("\\P", "\u{2029}"), ("\\u2029", "\u{2029}"), ("\\uFEFF", "\u{FEFF}"), ] @Test("An escape in a double-quoted scalar stands for its character, whatever the character is", arguments: escaped) func test_escapeStandsForItsCharacter(_ escape: (source: String, character: String)) throws { #expect(try PureYAML.parse("\"\(escape.source)\"") == .string(escape.character)) #expect(try PureYAML.parse("\"a\(escape.source)b\"") == .string("a\(escape.character)b")) #expect(try PureYAML.parse("k: \"\(escape.source)\"") == .mapping(.init([.init(key: "k", value: .string(escape.character))]))) } /// Strings a writer has to quote or escape, so that the reader gets the same string back. static let strings: [String] = [ "", " ", "x", "a b", "true", "null", "1", "1.5", "- x", "a: b", "# c", "\u{0}", "\u{1}", "\u{1F}", "\u{7F}", "\u{80}", "\u{85}", "\u{9F}", "\u{A0}", "\u{2028}", "\u{2029}", "a\u{2028}b", "a\u{85}b", "\u{FEFF}", "\u{FEFF}x", "x\u{FEFF}", "a\u{FEFF}b", "\u{FFFE}", "\u{FFFF}", "tab\there", "line\nbreak", "cr\rlf", "\r\n", "\u{200B}", "é", "日本語", "😀", ] @Test("A string that is dumped is read back as the same string", arguments: strings) func test_dumpedStringIsReadBack(_ string: String) throws { let value = PureYAML.Model.Value.string(string) let dumped = PureYAML.dump(value) #expect(try PureYAML.parse(dumped) == value, "\(string.unicodeScalars.map(\.value)) dumped as \(dumped.debugDescription)") let inside = PureYAML.Model.Value.mapping(.init([.init(key: "k", value: value)])) let dumpedInside = PureYAML.dump(inside) #expect(try PureYAML.parse(dumpedInside) == inside, "\(string.unicodeScalars.map(\.value)) dumped as \(dumpedInside.debugDescription)") let asKey = PureYAML.Model.Value.mapping(.init([.init(key: string, value: .int(1))])) let dumpedKey = PureYAML.dump(asKey) #expect(try PureYAML.parse(dumpedKey) == asKey, "\(string.unicodeScalars.map(\.value)) dumped as \(dumpedKey.debugDescription)") } }