| // RUN: %target-run-simple-swift |
| // REQUIRES: executable_test |
| |
| // REQUIRES: objc_interop |
| |
| // |
| // Tests for the NSString APIs as exposed by String |
| // |
| |
| import StdlibUnittest |
| |
| |
| import Foundation |
| import StdlibUnittestFoundationExtras |
| |
| // The most simple subclass of NSString that CoreFoundation does not know |
| // about. |
| class NonContiguousNSString : NSString { |
| required init(coder aDecoder: NSCoder) { |
| fatalError("don't call this initializer") |
| } |
| |
| override init() { |
| _value = [] |
| super.init() |
| } |
| |
| init(_ value: [UInt16]) { |
| _value = value |
| super.init() |
| } |
| |
| @objc(copyWithZone:) override func copy(with zone: NSZone?) -> Any { |
| // Ensure that copying this string produces a class that CoreFoundation |
| // does not know about. |
| return self |
| } |
| |
| @objc override var length: Int { |
| return _value.count |
| } |
| |
| @objc override func character(at index: Int) -> unichar { |
| return _value[index] |
| } |
| |
| var _value: [UInt16] |
| } |
| |
| let temporaryFileContents = |
| "Lorem ipsum dolor sit amet, consectetur adipisicing elit,\n" + |
| "sed do eiusmod tempor incididunt ut labore et dolore magna\n" + |
| "aliqua.\n" |
| |
| func createNSStringTemporaryFile() |
| -> (existingPath: String, nonExistentPath: String) { |
| let existingPath = |
| createTemporaryFile("NSStringAPIs.", ".txt", temporaryFileContents) |
| let nonExistentPath = existingPath + "-NoNeXiStEnT" |
| return (existingPath, nonExistentPath) |
| } |
| |
| var NSStringAPIs = TestSuite("NSStringAPIs") |
| |
| NSStringAPIs.test("Encodings") { |
| let availableEncodings: [String.Encoding] = String.availableStringEncodings |
| expectNotEqual(0, availableEncodings.count) |
| |
| let defaultCStringEncoding = String.defaultCStringEncoding |
| expectTrue(availableEncodings.contains(defaultCStringEncoding)) |
| |
| expectNotEqual("", String.localizedName(of: .utf8)) |
| } |
| |
| NSStringAPIs.test("NSStringEncoding") { |
| // Make sure NSStringEncoding and its values are type-compatible. |
| var enc: String.Encoding |
| enc = .windowsCP1250 |
| enc = .utf32LittleEndian |
| enc = .utf32BigEndian |
| enc = .ascii |
| enc = .utf8 |
| } |
| |
| NSStringAPIs.test("localizedStringWithFormat(_:...)") { |
| var world: NSString = "world" |
| expectEqual("Hello, world!%42", String.localizedStringWithFormat( |
| "Hello, %@!%%%ld", world, 42)) |
| |
| withOverriddenLocaleCurrentLocale("en_US") { |
| expectEqual("0.5", String.localizedStringWithFormat("%g", 0.5)) |
| } |
| |
| withOverriddenLocaleCurrentLocale("uk") { |
| expectEqual("0,5", String.localizedStringWithFormat("%g", 0.5)) |
| } |
| } |
| |
| NSStringAPIs.test("init(contentsOfFile:encoding:error:)") { |
| let (existingPath, nonExistentPath) = createNSStringTemporaryFile() |
| |
| do { |
| let content = try String( |
| contentsOfFile: existingPath, encoding: .ascii) |
| expectEqual( |
| "Lorem ipsum dolor sit amet, consectetur adipisicing elit,", |
| content._lines[0]) |
| } catch { |
| expectUnreachableCatch(error) |
| } |
| |
| do { |
| let content = try String( |
| contentsOfFile: nonExistentPath, encoding: .ascii) |
| expectUnreachable() |
| } catch { |
| } |
| } |
| |
| NSStringAPIs.test("init(contentsOfFile:usedEncoding:error:)") { |
| let (existingPath, nonExistentPath) = createNSStringTemporaryFile() |
| |
| do { |
| var usedEncoding: String.Encoding = String.Encoding(rawValue: 0) |
| let content = try String( |
| contentsOfFile: existingPath, usedEncoding: &usedEncoding) |
| expectNotEqual(0, usedEncoding.rawValue) |
| expectEqual( |
| "Lorem ipsum dolor sit amet, consectetur adipisicing elit,", |
| content._lines[0]) |
| } catch { |
| expectUnreachableCatch(error) |
| } |
| |
| var usedEncoding: String.Encoding = String.Encoding(rawValue: 0) |
| do { |
| _ = try String(contentsOfFile: nonExistentPath) |
| expectUnreachable() |
| } catch { |
| expectEqual(0, usedEncoding.rawValue) |
| } |
| } |
| |
| |
| NSStringAPIs.test("init(contentsOf:encoding:error:)") { |
| let (existingPath, nonExistentPath) = createNSStringTemporaryFile() |
| let existingURL = URL(string: "file://" + existingPath)! |
| let nonExistentURL = URL(string: "file://" + nonExistentPath)! |
| do { |
| let content = try String( |
| contentsOf: existingURL, encoding: .ascii) |
| expectEqual( |
| "Lorem ipsum dolor sit amet, consectetur adipisicing elit,", |
| content._lines[0]) |
| } catch { |
| expectUnreachableCatch(error) |
| } |
| |
| do { |
| _ = try String(contentsOf: nonExistentURL, encoding: .ascii) |
| expectUnreachable() |
| } catch { |
| } |
| } |
| |
| NSStringAPIs.test("init(contentsOf:usedEncoding:error:)") { |
| let (existingPath, nonExistentPath) = createNSStringTemporaryFile() |
| let existingURL = URL(string: "file://" + existingPath)! |
| let nonExistentURL = URL(string: "file://" + nonExistentPath)! |
| do { |
| var usedEncoding: String.Encoding = String.Encoding(rawValue: 0) |
| let content = try String( |
| contentsOf: existingURL, usedEncoding: &usedEncoding) |
| |
| expectNotEqual(0, usedEncoding.rawValue) |
| expectEqual( |
| "Lorem ipsum dolor sit amet, consectetur adipisicing elit,", |
| content._lines[0]) |
| } catch { |
| expectUnreachableCatch(error) |
| } |
| |
| var usedEncoding: String.Encoding = String.Encoding(rawValue: 0) |
| do { |
| _ = try String(contentsOf: nonExistentURL, usedEncoding: &usedEncoding) |
| expectUnreachable() |
| } catch { |
| expectEqual(0, usedEncoding.rawValue) |
| } |
| } |
| |
| NSStringAPIs.test("init(cString_:encoding:)") { |
| expectOptionalEqual("foo, a basmati bar!", |
| String(cString: |
| "foo, a basmati bar!", encoding: String.defaultCStringEncoding)) |
| } |
| |
| NSStringAPIs.test("init(utf8String:)") { |
| var s = "foo あいう" |
| var up = UnsafeMutablePointer<UInt8>.allocate(capacity: 100) |
| var i = 0 |
| for b in s.utf8 { |
| up[i] = b |
| i += 1 |
| } |
| up[i] = 0 |
| let cstr = UnsafeMutableRawPointer(up) |
| .bindMemory(to: CChar.self, capacity: 100) |
| expectOptionalEqual(s, String(utf8String: cstr)) |
| up.deallocate(capacity: 100) |
| } |
| |
| NSStringAPIs.test("canBeConvertedToEncoding(_:)") { |
| expectTrue("foo".canBeConverted(to: .ascii)) |
| expectFalse("あいう".canBeConverted(to: .ascii)) |
| } |
| |
| NSStringAPIs.test("capitalized") { |
| expectEqual("Foo Foo Foo Foo", "foo Foo fOO FOO".capitalized) |
| expectEqual("Жжж", "жжж".capitalized) |
| } |
| |
| NSStringAPIs.test("localizedCapitalized") { |
| if #available(OSX 10.11, iOS 9.0, *) { |
| withOverriddenLocaleCurrentLocale("en") { () -> Void in |
| expectEqual( |
| "Foo Foo Foo Foo", |
| "foo Foo fOO FOO".localizedCapitalized) |
| expectEqual("Жжж", "жжж".localizedCapitalized) |
| return () |
| } |
| |
| // |
| // Special casing. |
| // |
| |
| // U+0069 LATIN SMALL LETTER I |
| // to upper case: |
| // U+0049 LATIN CAPITAL LETTER I |
| withOverriddenLocaleCurrentLocale("en") { |
| expectEqual("Iii Iii", "iii III".localizedCapitalized) |
| } |
| |
| // U+0069 LATIN SMALL LETTER I |
| // to upper case in Turkish locale: |
| // U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE |
| withOverriddenLocaleCurrentLocale("tr") { |
| expectEqual("\u{0130}ii Iıı", "iii III".localizedCapitalized) |
| } |
| } |
| } |
| |
| /// Checks that executing the operation in the locale with the given |
| /// `localeID` (or if `localeID` is `nil`, the current locale) gives |
| /// the expected result, and that executing the operation with a nil |
| /// locale gives the same result as explicitly passing the system |
| /// locale. |
| /// |
| /// - Parameter expected: the expected result when the operation is |
| /// executed in the given localeID |
| func expectLocalizedEquality( |
| _ expected: String, |
| _ op: (_: Locale?) -> String, |
| _ localeID: String? = nil, |
| _ message: @autoclosure () -> String = "", |
| showFrame: Bool = true, |
| stackTrace: SourceLocStack = SourceLocStack(), |
| file: String = #file, line: UInt = #line |
| ) { |
| let trace = stackTrace.pushIf(showFrame, file: file, line: line) |
| |
| let locale = localeID.map { |
| Locale(identifier: $0) |
| } ?? Locale.current |
| |
| expectEqual( |
| expected, op(locale), |
| message(), stackTrace: trace) |
| } |
| |
| NSStringAPIs.test("capitalizedString(with:)") { |
| expectLocalizedEquality( |
| "Foo Foo Foo Foo", |
| { loc in "foo Foo fOO FOO".capitalized(with: loc) }) |
| |
| expectLocalizedEquality("Жжж", { loc in "жжж".capitalized(with: loc) }) |
| |
| expectEqual( |
| "Foo Foo Foo Foo", |
| "foo Foo fOO FOO".capitalized(with: nil)) |
| expectEqual("Жжж", "жжж".capitalized(with: nil)) |
| |
| // |
| // Special casing. |
| // |
| |
| // U+0069 LATIN SMALL LETTER I |
| // to upper case: |
| // U+0049 LATIN CAPITAL LETTER I |
| expectLocalizedEquality( |
| "Iii Iii", |
| { loc in "iii III".capitalized(with: loc) }, "en") |
| |
| // U+0069 LATIN SMALL LETTER I |
| // to upper case in Turkish locale: |
| // U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE |
| expectLocalizedEquality( |
| "İii Iıı", |
| { loc in "iii III".capitalized(with: loc) }, "tr") |
| } |
| |
| NSStringAPIs.test("caseInsensitiveCompare(_:)") { |
| expectEqual(ComparisonResult.orderedSame, |
| "abCD".caseInsensitiveCompare("AbCd")) |
| expectEqual(ComparisonResult.orderedAscending, |
| "abCD".caseInsensitiveCompare("AbCdE")) |
| |
| expectEqual(ComparisonResult.orderedSame, |
| "абвг".caseInsensitiveCompare("АбВг")) |
| expectEqual(ComparisonResult.orderedAscending, |
| "абВГ".caseInsensitiveCompare("АбВгД")) |
| } |
| |
| NSStringAPIs.test("commonPrefix(with:options:)") { |
| expectEqual("ab", |
| "abcd".commonPrefix(with: "abdc", options: [])) |
| expectEqual("abC", |
| "abCd".commonPrefix(with: "abce", options: .caseInsensitive)) |
| |
| expectEqual("аб", |
| "абвг".commonPrefix(with: "абгв", options: [])) |
| expectEqual("абВ", |
| "абВг".commonPrefix(with: "абвд", options: .caseInsensitive)) |
| } |
| |
| NSStringAPIs.test("compare(_:options:range:locale:)") { |
| expectEqual(ComparisonResult.orderedSame, |
| "abc".compare("abc")) |
| expectEqual(ComparisonResult.orderedAscending, |
| "абв".compare("где")) |
| |
| expectEqual(ComparisonResult.orderedSame, |
| "abc".compare("abC", options: .caseInsensitive)) |
| expectEqual(ComparisonResult.orderedSame, |
| "абв".compare("абВ", options: .caseInsensitive)) |
| |
| do { |
| let s = "abcd" |
| let r = s.index(after: s.startIndex)..<s.endIndex |
| expectEqual(ComparisonResult.orderedSame, |
| s.compare("bcd", range: r)) |
| } |
| do { |
| let s = "абвг" |
| let r = s.index(after: s.startIndex)..<s.endIndex |
| expectEqual(ComparisonResult.orderedSame, |
| s.compare("бвг", range: r)) |
| } |
| |
| expectEqual(ComparisonResult.orderedSame, |
| "abc".compare("abc", locale: Locale.current)) |
| expectEqual(ComparisonResult.orderedSame, |
| "абв".compare("абв", locale: Locale.current)) |
| } |
| |
| NSStringAPIs.test("completePath(into:caseSensitive:matchesInto:filterTypes)") { |
| let (existingPath, nonExistentPath) = createNSStringTemporaryFile() |
| do { |
| var count = nonExistentPath.completePath(caseSensitive: false) |
| expectEqual(0, count) |
| } |
| |
| do { |
| var outputName = "None Found" |
| var count = nonExistentPath.completePath( |
| into: &outputName, caseSensitive: false) |
| |
| expectEqual(0, count) |
| expectEqual("None Found", outputName) |
| } |
| |
| do { |
| var outputName = "None Found" |
| var outputArray: [String] = ["foo", "bar"] |
| var count = nonExistentPath.completePath( |
| into: &outputName, caseSensitive: false, matchesInto: &outputArray) |
| |
| expectEqual(0, count) |
| expectEqual("None Found", outputName) |
| expectEqual(["foo", "bar"], outputArray) |
| } |
| |
| do { |
| var count = existingPath.completePath(caseSensitive: false) |
| expectEqual(1, count) |
| } |
| |
| do { |
| var outputName = "None Found" |
| var count = existingPath.completePath( |
| into: &outputName, caseSensitive: false) |
| |
| expectEqual(1, count) |
| expectEqual(existingPath, outputName) |
| } |
| |
| do { |
| var outputName = "None Found" |
| var outputArray: [String] = ["foo", "bar"] |
| var count = existingPath.completePath( |
| into: &outputName, caseSensitive: false, matchesInto: &outputArray) |
| |
| expectEqual(1, count) |
| expectEqual(existingPath, outputName) |
| expectEqual([existingPath], outputArray) |
| } |
| |
| do { |
| var outputName = "None Found" |
| var count = existingPath.completePath( |
| into: &outputName, caseSensitive: false, filterTypes: ["txt"]) |
| |
| expectEqual(1, count) |
| expectEqual(existingPath, outputName) |
| } |
| } |
| |
| NSStringAPIs.test("components(separatedBy:) (NSCharacterSet)") { |
| expectEqual([""], "".components( |
| separatedBy: CharacterSet.decimalDigits)) |
| |
| expectEqual( |
| ["абв", "", "あいう", "abc"], |
| "абв12あいう3abc".components( |
| separatedBy: CharacterSet.decimalDigits)) |
| |
| expectEqual( |
| ["абв", "", "あいう", "abc"], |
| "абв\u{1F601}\u{1F602}あいう\u{1F603}abc" |
| .components( |
| separatedBy: CharacterSet(charactersIn: "\u{1F601}\u{1F602}\u{1F603}"))) |
| |
| // Performs Unicode scalar comparison. |
| expectEqual( |
| ["abcし\u{3099}def"], |
| "abcし\u{3099}def".components( |
| separatedBy: CharacterSet(charactersIn: "\u{3058}"))) |
| } |
| |
| NSStringAPIs.test("components(separatedBy:) (String)") { |
| expectEqual([""], "".components(separatedBy: "//")) |
| |
| expectEqual( |
| ["абв", "あいう", "abc"], |
| "абв//あいう//abc".components(separatedBy: "//")) |
| |
| // Performs normalization. |
| expectEqual( |
| ["abc", "def"], |
| "abcし\u{3099}def".components(separatedBy: "\u{3058}")) |
| } |
| |
| NSStringAPIs.test("cString(usingEncoding:)") { |
| expectEmpty("абв".cString(using: .ascii)) |
| |
| let expectedBytes: [UInt8] = [ 0xd0, 0xb0, 0xd0, 0xb1, 0xd0, 0xb2, 0 ] |
| var expectedStr: [CChar] = expectedBytes.map { CChar(bitPattern: $0) } |
| expectEqual(expectedStr, |
| "абв".cString(using: .utf8)!) |
| } |
| |
| NSStringAPIs.test("data(usingEncoding:allowLossyConversion:)") { |
| expectEmpty("あいう".data(using: .ascii, allowLossyConversion: false)) |
| |
| do { |
| let data = "あいう".data(using: .utf8)! |
| let expectedBytes: [UInt8] = [ |
| 0xe3, 0x81, 0x82, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x86 |
| ] |
| expectEqualSequence(expectedBytes, data) |
| } |
| } |
| |
| NSStringAPIs.test("init(data:encoding:)") { |
| let bytes: [UInt8] = [0xe3, 0x81, 0x82, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x86] |
| let data = Data(bytes: bytes) |
| |
| expectEmpty(String(data: data, encoding: .nonLossyASCII)) |
| |
| expectEqualSequence( |
| "あいう".characters, |
| String(data: data, encoding: .utf8)!.characters) |
| } |
| |
| NSStringAPIs.test("decomposedStringWithCanonicalMapping") { |
| expectEqual("abc", "abc".decomposedStringWithCanonicalMapping) |
| expectEqual("\u{305f}\u{3099}くてん", "だくてん".decomposedStringWithCanonicalMapping) |
| expectEqual("\u{ff80}\u{ff9e}クテン", "ダクテン".decomposedStringWithCanonicalMapping) |
| } |
| |
| NSStringAPIs.test("decomposedStringWithCompatibilityMapping") { |
| expectEqual("abc", "abc".decomposedStringWithCompatibilityMapping) |
| expectEqual("\u{30bf}\u{3099}クテン", "ダクテン".decomposedStringWithCompatibilityMapping) |
| } |
| |
| NSStringAPIs.test("enumerateLines(_:)") { |
| var lines: [String] = [] |
| "abc\n\ndefghi\njklm".enumerateLines { |
| (line: String, stop: inout Bool) |
| in |
| lines.append(line) |
| if lines.count == 3 { |
| stop = true |
| } |
| } |
| expectEqual(["abc", "", "defghi"], lines) |
| } |
| |
| NSStringAPIs.test("enumerateLinguisticTagsIn(_:scheme:options:orthography:_:") { |
| let s = "Абв. Глокая куздра штеко будланула бокра и кудрячит бокрёнка. Абв." |
| let startIndex = s.index(s.startIndex, offsetBy: 5) |
| let endIndex = s.index(s.startIndex, offsetBy: 62) |
| var tags: [String] = [] |
| var tokens: [String] = [] |
| var sentences: [String] = [] |
| s.enumerateLinguisticTags(in: startIndex..<endIndex, |
| scheme: NSLinguisticTagSchemeTokenType, |
| options: [], |
| orthography: nil) { |
| (tag: String, tokenRange: Range<String.Index>, sentenceRange: Range<String.Index>, stop: inout Bool) |
| in |
| tags.append(tag) |
| tokens.append(s[tokenRange]) |
| sentences.append(s[sentenceRange]) |
| if tags.count == 3 { |
| stop = true |
| } |
| } |
| expectEqual( |
| [NSLinguisticTagWord, NSLinguisticTagWhitespace, NSLinguisticTagWord], |
| tags) |
| expectEqual(["Глокая", " ", "куздра"], tokens) |
| let sentence = s[startIndex..<endIndex] |
| expectEqual([sentence, sentence, sentence], sentences) |
| } |
| |
| NSStringAPIs.test("enumerateSubstringsIn(_:options:_:)") { |
| let s = "え\u{304b}\u{3099}お\u{263a}\u{fe0f}😀😊" |
| let startIndex = s.index(s.startIndex, offsetBy: 1) |
| let endIndex = s.index(s.startIndex, offsetBy: 5) |
| do { |
| var substrings: [String] = [] |
| s.enumerateSubstrings(in: startIndex..<endIndex, |
| options: String.EnumerationOptions.byComposedCharacterSequences) { |
| (substring: String?, substringRange: Range<String.Index>, |
| enclosingRange: Range<String.Index>, stop: inout Bool) |
| in |
| substrings.append(substring!) |
| expectEqual(substring, s[substringRange]) |
| expectEqual(substring, s[enclosingRange]) |
| } |
| expectEqual(["\u{304b}\u{3099}", "お", "☺️", "😀"], substrings) |
| } |
| do { |
| var substrings: [String] = [] |
| s.enumerateSubstrings(in: startIndex..<endIndex, |
| options: [.byComposedCharacterSequences, .substringNotRequired]) { |
| (substring_: String?, substringRange: Range<String.Index>, |
| enclosingRange: Range<String.Index>, stop: inout Bool) |
| in |
| expectEmpty(substring_) |
| let substring = s[substringRange] |
| substrings.append(substring) |
| expectEqual(substring, s[enclosingRange]) |
| } |
| expectEqual(["\u{304b}\u{3099}", "お", "☺️", "😀"], substrings) |
| } |
| } |
| |
| NSStringAPIs.test("fastestEncoding") { |
| let availableEncodings: [String.Encoding] = String.availableStringEncodings |
| expectTrue(availableEncodings.contains("abc".fastestEncoding)) |
| } |
| |
| NSStringAPIs.test("getBytes(_:maxLength:usedLength:encoding:options:range:remaining:)") { |
| let s = "abc абв def где gh жз zzz" |
| let startIndex = s.index(s.startIndex, offsetBy: 8) |
| let endIndex = s.index(s.startIndex, offsetBy: 22) |
| do { |
| // 'maxLength' is limiting. |
| let bufferLength = 100 |
| var expectedStr: [UInt8] = Array("def где ".utf8) |
| while (expectedStr.count != bufferLength) { |
| expectedStr.append(0xff) |
| } |
| var buffer = [UInt8](repeating: 0xff, count: bufferLength) |
| var usedLength = 0 |
| var remainingRange = startIndex..<endIndex |
| var result = s.getBytes(&buffer, maxLength: 11, usedLength: &usedLength, |
| encoding: .utf8, |
| options: [], |
| range: startIndex..<endIndex, remaining: &remainingRange) |
| expectTrue(result) |
| expectEqualSequence(expectedStr, buffer) |
| expectEqual(11, usedLength) |
| expectEqual(remainingRange.lowerBound, s.index(startIndex, offsetBy: 8)) |
| expectEqual(remainingRange.upperBound, endIndex) |
| } |
| do { |
| // 'bufferLength' is limiting. Note that the buffer is not filled |
| // completely, since doing that would break a UTF sequence. |
| let bufferLength = 5 |
| var expectedStr: [UInt8] = Array("def ".utf8) |
| while (expectedStr.count != bufferLength) { |
| expectedStr.append(0xff) |
| } |
| var buffer = [UInt8](repeating: 0xff, count: bufferLength) |
| var usedLength = 0 |
| var remainingRange = startIndex..<endIndex |
| var result = s.getBytes(&buffer, maxLength: 11, usedLength: &usedLength, |
| encoding: .utf8, |
| options: [], |
| range: startIndex..<endIndex, remaining: &remainingRange) |
| expectTrue(result) |
| expectEqualSequence(expectedStr, buffer) |
| expectEqual(4, usedLength) |
| expectEqual(remainingRange.lowerBound, s.index(startIndex, offsetBy: 4)) |
| expectEqual(remainingRange.upperBound, endIndex) |
| } |
| do { |
| // 'range' is converted completely. |
| let bufferLength = 100 |
| var expectedStr: [UInt8] = Array("def где gh жз ".utf8) |
| while (expectedStr.count != bufferLength) { |
| expectedStr.append(0xff) |
| } |
| var buffer = [UInt8](repeating: 0xff, count: bufferLength) |
| var usedLength = 0 |
| var remainingRange = startIndex..<endIndex |
| var result = s.getBytes(&buffer, maxLength: bufferLength, |
| usedLength: &usedLength, encoding: .utf8, |
| options: [], |
| range: startIndex..<endIndex, remaining: &remainingRange) |
| expectTrue(result) |
| expectEqualSequence(expectedStr, buffer) |
| expectEqual(19, usedLength) |
| expectEqual(remainingRange.lowerBound, endIndex) |
| expectEqual(remainingRange.upperBound, endIndex) |
| } |
| do { |
| // Inappropriate encoding. |
| let bufferLength = 100 |
| var expectedStr: [UInt8] = Array("def ".utf8) |
| while (expectedStr.count != bufferLength) { |
| expectedStr.append(0xff) |
| } |
| var buffer = [UInt8](repeating: 0xff, count: bufferLength) |
| var usedLength = 0 |
| var remainingRange = startIndex..<endIndex |
| var result = s.getBytes(&buffer, maxLength: bufferLength, |
| usedLength: &usedLength, encoding: .ascii, |
| options: [], |
| range: startIndex..<endIndex, remaining: &remainingRange) |
| expectTrue(result) |
| expectEqualSequence(expectedStr, buffer) |
| expectEqual(4, usedLength) |
| expectEqual(remainingRange.lowerBound, s.index(startIndex, offsetBy: 4)) |
| expectEqual(remainingRange.upperBound, endIndex) |
| } |
| } |
| |
| NSStringAPIs.test("getCString(_:maxLength:encoding:)") { |
| var s = "abc あかさた" |
| do { |
| // The largest buffer that cannot accommodate the string plus null terminator. |
| let bufferLength = 16 |
| var buffer = Array( |
| repeating: CChar(bitPattern: 0xff), count: bufferLength) |
| let result = s.getCString(&buffer, maxLength: 100, |
| encoding: .utf8) |
| expectFalse(result) |
| } |
| do { |
| // The smallest buffer where the result can fit. |
| let bufferLength = 17 |
| var expectedStr = "abc あかさた\0".utf8.map { CChar(bitPattern: $0) } |
| while (expectedStr.count != bufferLength) { |
| expectedStr.append(CChar(bitPattern: 0xff)) |
| } |
| var buffer = Array( |
| repeating: CChar(bitPattern: 0xff), count: bufferLength) |
| let result = s.getCString(&buffer, maxLength: 100, |
| encoding: .utf8) |
| expectTrue(result) |
| expectEqualSequence(expectedStr, buffer) |
| } |
| do { |
| // Limit buffer size with 'maxLength'. |
| let bufferLength = 100 |
| var buffer = Array( |
| repeating: CChar(bitPattern: 0xff), count: bufferLength) |
| let result = s.getCString(&buffer, maxLength: 8, |
| encoding: .utf8) |
| expectFalse(result) |
| } |
| do { |
| // String with unpaired surrogates. |
| let illFormedUTF16 = NonContiguousNSString([ 0xd800 ]) as String |
| let bufferLength = 100 |
| var buffer = Array( |
| repeating: CChar(bitPattern: 0xff), count: bufferLength) |
| let result = illFormedUTF16.getCString(&buffer, maxLength: 100, |
| encoding: .utf8) |
| expectFalse(result) |
| } |
| } |
| |
| NSStringAPIs.test("getLineStart(_:end:contentsEnd:forRange:)") { |
| let s = "Глокая куздра\nштеко будланула\nбокра и кудрячит\nбокрёнка." |
| let r = s.index(s.startIndex, offsetBy: 16)..<s.index(s.startIndex, offsetBy: 35) |
| do { |
| var outStartIndex = s.startIndex |
| var outLineEndIndex = s.startIndex |
| var outContentsEndIndex = s.startIndex |
| s.getLineStart(&outStartIndex, end: &outLineEndIndex, |
| contentsEnd: &outContentsEndIndex, for: r) |
| expectEqual("штеко будланула\nбокра и кудрячит\n", |
| s[outStartIndex..<outLineEndIndex]) |
| expectEqual("штеко будланула\nбокра и кудрячит", |
| s[outStartIndex..<outContentsEndIndex]) |
| } |
| } |
| |
| NSStringAPIs.test("getParagraphStart(_:end:contentsEnd:forRange:)") { |
| let s = "Глокая куздра\nштеко будланула\u{2028}бокра и кудрячит\u{2028}бокрёнка.\n Абв." |
| let r = s.index(s.startIndex, offsetBy: 16)..<s.index(s.startIndex, offsetBy: 35) |
| do { |
| var outStartIndex = s.startIndex |
| var outEndIndex = s.startIndex |
| var outContentsEndIndex = s.startIndex |
| s.getParagraphStart(&outStartIndex, end: &outEndIndex, |
| contentsEnd: &outContentsEndIndex, for: r) |
| expectEqual("штеко будланула\u{2028}бокра и кудрячит\u{2028}бокрёнка.\n", |
| s[outStartIndex..<outEndIndex]) |
| expectEqual("штеко будланула\u{2028}бокра и кудрячит\u{2028}бокрёнка.", |
| s[outStartIndex..<outContentsEndIndex]) |
| } |
| } |
| |
| NSStringAPIs.test("hash") { |
| var s: String = "abc" |
| var nsstr: NSString = "abc" |
| expectEqual(nsstr.hash, s.hash) |
| } |
| |
| NSStringAPIs.test("init(bytes:encoding:)") { |
| var s: String = "abc あかさた" |
| expectOptionalEqual( |
| s, String(bytes: s.utf8, encoding: .utf8)) |
| |
| /* |
| FIXME: Test disabled because the NSString documentation is unclear about |
| what should actually happen in this case. |
| |
| expectEmpty(String(bytes: bytes, length: bytes.count, |
| encoding: .ascii)) |
| */ |
| |
| // FIXME: add a test where this function actually returns nil. |
| } |
| |
| NSStringAPIs.test("init(bytesNoCopy:length:encoding:freeWhenDone:)") { |
| var s: String = "abc あかさた" |
| var bytes: [UInt8] = Array(s.utf8) |
| expectOptionalEqual(s, String(bytesNoCopy: &bytes, |
| length: bytes.count, encoding: .utf8, |
| freeWhenDone: false)) |
| |
| /* |
| FIXME: Test disabled because the NSString documentation is unclear about |
| what should actually happen in this case. |
| |
| expectEmpty(String(bytesNoCopy: &bytes, length: bytes.count, |
| encoding: .ascii, freeWhenDone: false)) |
| */ |
| |
| // FIXME: add a test where this function actually returns nil. |
| } |
| |
| NSStringAPIs.test("init(utf16CodeUnits:count:)") { |
| let expected = "abc абв \u{0001F60A}" |
| let chars: [unichar] = Array(expected.utf16) |
| |
| expectEqual(expected, String(utf16CodeUnits: chars, count: chars.count)) |
| } |
| |
| NSStringAPIs.test("init(utf16CodeUnitsNoCopy:count:freeWhenDone:)") { |
| let expected = "abc абв \u{0001F60A}" |
| let chars: [unichar] = Array(expected.utf16) |
| |
| expectEqual(expected, String(utf16CodeUnitsNoCopy: chars, |
| count: chars.count, freeWhenDone: false)) |
| } |
| |
| NSStringAPIs.test("init(format:_:...)") { |
| expectEqual("", String(format: "")) |
| expectEqual( |
| "abc абв \u{0001F60A}", String(format: "abc абв \u{0001F60A}")) |
| |
| let world: NSString = "world" |
| expectEqual("Hello, world!%42", |
| String(format: "Hello, %@!%%%ld", world, 42)) |
| |
| // test for rdar://problem/18317906 |
| expectEqual("3.12", String(format: "%.2f", 3.123456789)) |
| expectEqual("3.12", NSString(format: "%.2f", 3.123456789)) |
| } |
| |
| NSStringAPIs.test("init(format:arguments:)") { |
| expectEqual("", String(format: "", arguments: [])) |
| expectEqual( |
| "abc абв \u{0001F60A}", |
| String(format: "abc абв \u{0001F60A}", arguments: [])) |
| |
| let world: NSString = "world" |
| let args: [CVarArg] = [ world, 42 ] |
| expectEqual("Hello, world!%42", |
| String(format: "Hello, %@!%%%ld", arguments: args)) |
| } |
| |
| NSStringAPIs.test("init(format:locale:_:...)") { |
| var world: NSString = "world" |
| expectEqual("Hello, world!%42", String(format: "Hello, %@!%%%ld", |
| locale: nil, world, 42)) |
| } |
| |
| NSStringAPIs.test("init(format:locale:arguments:)") { |
| let world: NSString = "world" |
| let args: [CVarArg] = [ world, 42 ] |
| expectEqual("Hello, world!%42", String(format: "Hello, %@!%%%ld", |
| locale: nil, arguments: args)) |
| } |
| |
| NSStringAPIs.test("utf16Count") { |
| expectEqual(1, "a".utf16.count) |
| expectEqual(2, "\u{0001F60A}".utf16.count) |
| } |
| |
| NSStringAPIs.test("lengthOfBytesUsingEncoding(_:)") { |
| expectEqual(1, "a".lengthOfBytes(using: .utf8)) |
| expectEqual(2, "あ".lengthOfBytes(using: .shiftJIS)) |
| } |
| |
| NSStringAPIs.test("lineRangeFor(_:)") { |
| let s = "Глокая куздра\nштеко будланула\nбокра и кудрячит\nбокрёнка." |
| let r = s.index(s.startIndex, offsetBy: 16)..<s.index(s.startIndex, offsetBy: 35) |
| do { |
| let result = s.lineRange(for: r) |
| expectEqual("штеко будланула\nбокра и кудрячит\n", s[result]) |
| } |
| } |
| |
| NSStringAPIs.test("linguisticTagsIn(_:scheme:options:orthography:tokenRanges:)") { |
| let s = "Абв. Глокая куздра штеко будланула бокра и кудрячит бокрёнка. Абв." |
| let startIndex = s.index(s.startIndex, offsetBy: 5) |
| let endIndex = s.index(s.startIndex, offsetBy: 17) |
| var tokenRanges: [Range<String.Index>] = [] |
| var tags = s.linguisticTags(in: startIndex..<endIndex, |
| scheme: NSLinguisticTagSchemeTokenType, |
| options: [], |
| orthography: nil, tokenRanges: &tokenRanges) |
| expectEqual( |
| [NSLinguisticTagWord, NSLinguisticTagWhitespace, NSLinguisticTagWord], |
| tags) |
| expectEqual(["Глокая", " ", "куздра"], |
| tokenRanges.map { s[$0] } ) |
| } |
| |
| NSStringAPIs.test("localizedCaseInsensitiveCompare(_:)") { |
| expectEqual(ComparisonResult.orderedSame, |
| "abCD".localizedCaseInsensitiveCompare("AbCd")) |
| expectEqual(ComparisonResult.orderedAscending, |
| "abCD".localizedCaseInsensitiveCompare("AbCdE")) |
| |
| expectEqual(ComparisonResult.orderedSame, |
| "абвг".localizedCaseInsensitiveCompare("АбВг")) |
| expectEqual(ComparisonResult.orderedAscending, |
| "абВГ".localizedCaseInsensitiveCompare("АбВгД")) |
| } |
| |
| NSStringAPIs.test("localizedCompare(_:)") { |
| expectEqual(ComparisonResult.orderedAscending, |
| "abCD".localizedCompare("AbCd")) |
| |
| expectEqual(ComparisonResult.orderedAscending, |
| "абвг".localizedCompare("АбВг")) |
| } |
| |
| NSStringAPIs.test("localizedStandardCompare(_:)") { |
| expectEqual(ComparisonResult.orderedAscending, |
| "abCD".localizedStandardCompare("AbCd")) |
| |
| expectEqual(ComparisonResult.orderedAscending, |
| "абвг".localizedStandardCompare("АбВг")) |
| } |
| |
| NSStringAPIs.test("localizedLowercase") { |
| if #available(OSX 10.11, iOS 9.0, *) { |
| withOverriddenLocaleCurrentLocale("en") { |
| expectEqual("abcd", "abCD".localizedLowercase) |
| } |
| |
| withOverriddenLocaleCurrentLocale("en") { |
| expectEqual("абвг", "абВГ".localizedLowercase) |
| } |
| withOverriddenLocaleCurrentLocale("ru") { |
| expectEqual("абвг", "абВГ".localizedLowercase) |
| } |
| |
| withOverriddenLocaleCurrentLocale("ru") { |
| expectEqual("たちつてと", "たちつてと".localizedLowercase) |
| } |
| |
| // |
| // Special casing. |
| // |
| |
| // U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE |
| // to lower case: |
| // U+0069 LATIN SMALL LETTER I |
| // U+0307 COMBINING DOT ABOVE |
| withOverriddenLocaleCurrentLocale("en") { |
| expectEqual("\u{0069}\u{0307}", "\u{0130}".localizedLowercase) |
| } |
| |
| // U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE |
| // to lower case in Turkish locale: |
| // U+0069 LATIN SMALL LETTER I |
| withOverriddenLocaleCurrentLocale("tr") { |
| expectEqual("\u{0069}", "\u{0130}".localizedLowercase) |
| } |
| |
| // U+0049 LATIN CAPITAL LETTER I |
| // U+0307 COMBINING DOT ABOVE |
| // to lower case: |
| // U+0069 LATIN SMALL LETTER I |
| // U+0307 COMBINING DOT ABOVE |
| withOverriddenLocaleCurrentLocale("en") { |
| expectEqual( |
| "\u{0069}\u{0307}", |
| "\u{0049}\u{0307}".localizedLowercase) |
| } |
| |
| // U+0049 LATIN CAPITAL LETTER I |
| // U+0307 COMBINING DOT ABOVE |
| // to lower case in Turkish locale: |
| // U+0069 LATIN SMALL LETTER I |
| withOverriddenLocaleCurrentLocale("tr") { |
| expectEqual("\u{0069}", "\u{0049}\u{0307}".localizedLowercase) |
| } |
| } |
| } |
| |
| NSStringAPIs.test("lowercased(with:)") { |
| expectLocalizedEquality("abcd", { loc in "abCD".lowercased(with: loc) }, "en") |
| |
| expectLocalizedEquality("абвг", { loc in "абВГ".lowercased(with: loc) }, "en") |
| expectLocalizedEquality("абвг", { loc in "абВГ".lowercased(with: loc) }, "ru") |
| |
| expectLocalizedEquality("たちつてと", { loc in "たちつてと".lowercased(with: loc) }, "ru") |
| |
| // |
| // Special casing. |
| // |
| |
| // U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE |
| // to lower case: |
| // U+0069 LATIN SMALL LETTER I |
| // U+0307 COMBINING DOT ABOVE |
| expectLocalizedEquality("\u{0069}\u{0307}", { loc in "\u{0130}".lowercased(with: loc) }, "en") |
| |
| // U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE |
| // to lower case in Turkish locale: |
| // U+0069 LATIN SMALL LETTER I |
| expectLocalizedEquality("\u{0069}", { loc in "\u{0130}".lowercased(with: loc) }, "tr") |
| |
| // U+0049 LATIN CAPITAL LETTER I |
| // U+0307 COMBINING DOT ABOVE |
| // to lower case: |
| // U+0069 LATIN SMALL LETTER I |
| // U+0307 COMBINING DOT ABOVE |
| expectLocalizedEquality("\u{0069}\u{0307}", { loc in "\u{0049}\u{0307}".lowercased(with: loc) }, "en") |
| |
| // U+0049 LATIN CAPITAL LETTER I |
| // U+0307 COMBINING DOT ABOVE |
| // to lower case in Turkish locale: |
| // U+0069 LATIN SMALL LETTER I |
| expectLocalizedEquality("\u{0069}", { loc in "\u{0049}\u{0307}".lowercased(with: loc) }, "tr") |
| } |
| |
| NSStringAPIs.test("maximumLengthOfBytesUsingEncoding(_:)") { |
| do { |
| let s = "abc" |
| expectLE(s.utf8.count, |
| s.maximumLengthOfBytes(using: .utf8)) |
| } |
| do { |
| let s = "abc абв" |
| expectLE(s.utf8.count, |
| s.maximumLengthOfBytes(using: .utf8)) |
| } |
| do { |
| let s = "\u{1F60A}" |
| expectLE(s.utf8.count, |
| s.maximumLengthOfBytes(using: .utf8)) |
| } |
| } |
| |
| NSStringAPIs.test("paragraphRangeFor(_:)") { |
| let s = "Глокая куздра\nштеко будланула\u{2028}бокра и кудрячит\u{2028}бокрёнка.\n Абв." |
| let r = s.index(s.startIndex, offsetBy: 16)..<s.index(s.startIndex, offsetBy: 35) |
| do { |
| let result = s.paragraphRange(for: r) |
| expectEqual("штеко будланула\u{2028}бокра и кудрячит\u{2028}бокрёнка.\n", s[result]) |
| } |
| } |
| |
| NSStringAPIs.test("pathComponents") { |
| expectEqual([ "/", "foo", "bar" ] as [NSString], ("/foo/bar" as NSString).pathComponents as [NSString]) |
| expectEqual([ "/", "абв", "где" ] as [NSString], ("/абв/где" as NSString).pathComponents as [NSString]) |
| } |
| |
| NSStringAPIs.test("precomposedStringWithCanonicalMapping") { |
| expectEqual("abc", "abc".precomposedStringWithCanonicalMapping) |
| expectEqual("だくてん", |
| "\u{305f}\u{3099}くてん".precomposedStringWithCanonicalMapping) |
| expectEqual("ダクテン", |
| "\u{ff80}\u{ff9e}クテン".precomposedStringWithCanonicalMapping) |
| expectEqual("\u{fb03}", "\u{fb03}".precomposedStringWithCanonicalMapping) |
| } |
| |
| NSStringAPIs.test("precomposedStringWithCompatibilityMapping") { |
| expectEqual("abc", "abc".precomposedStringWithCompatibilityMapping) |
| /* |
| Test disabled because of: |
| <rdar://problem/17041347> NFKD normalization as implemented by |
| 'precomposedStringWithCompatibilityMapping:' is not idempotent |
| |
| expectEqual("\u{30c0}クテン", |
| "\u{ff80}\u{ff9e}クテン".precomposedStringWithCompatibilityMapping) |
| */ |
| expectEqual("ffi", "\u{fb03}".precomposedStringWithCompatibilityMapping) |
| } |
| |
| NSStringAPIs.test("propertyList()") { |
| expectEqual(["foo", "bar"], |
| "(\"foo\", \"bar\")".propertyList() as! [String]) |
| } |
| |
| NSStringAPIs.test("propertyListFromStringsFileFormat()") { |
| expectEqual(["foo": "bar", "baz": "baz"], |
| "/* comment */\n\"foo\" = \"bar\";\n\"baz\";" |
| .propertyListFromStringsFileFormat() as Dictionary<String, String>) |
| } |
| |
| NSStringAPIs.test("rangeOfCharacterFrom(_:options:range:)") { |
| do { |
| let charset = CharacterSet(charactersIn: "абв") |
| do { |
| let s = "Глокая куздра" |
| let r = s.rangeOfCharacter(from: charset)! |
| expectEqual(s.index(s.startIndex, offsetBy: 4), r.lowerBound) |
| expectEqual(s.index(s.startIndex, offsetBy: 5), r.upperBound) |
| } |
| do { |
| expectEmpty("клмн".rangeOfCharacter(from: charset)) |
| } |
| do { |
| let s = "абвклмнабвклмн" |
| let r = s.rangeOfCharacter(from: charset, |
| options: .backwards)! |
| expectEqual(s.index(s.startIndex, offsetBy: 9), r.lowerBound) |
| expectEqual(s.index(s.startIndex, offsetBy: 10), r.upperBound) |
| } |
| do { |
| let s = "абвклмнабв" |
| let r = s.rangeOfCharacter(from: charset, |
| range: s.index(s.startIndex, offsetBy: 3)..<s.endIndex)! |
| expectEqual(s.index(s.startIndex, offsetBy: 7), r.lowerBound) |
| expectEqual(s.index(s.startIndex, offsetBy: 8), r.upperBound) |
| } |
| } |
| |
| do { |
| let charset = CharacterSet(charactersIn: "\u{305f}\u{3099}") |
| expectEmpty("\u{3060}".rangeOfCharacter(from: charset)) |
| } |
| do { |
| let charset = CharacterSet(charactersIn: "\u{3060}") |
| expectEmpty("\u{305f}\u{3099}".rangeOfCharacter(from: charset)) |
| } |
| |
| do { |
| let charset = CharacterSet(charactersIn: "\u{1F600}") |
| do { |
| let s = "abc\u{1F600}" |
| expectEqual("\u{1F600}", |
| s[s.rangeOfCharacter(from: charset)!]) |
| } |
| do { |
| expectEmpty("abc\u{1F601}".rangeOfCharacter(from: charset)) |
| } |
| } |
| } |
| |
| NSStringAPIs.test("rangeOfComposedCharacterSequence(at:)") { |
| let s = "\u{1F601}abc \u{305f}\u{3099} def" |
| expectEqual("\u{1F601}", s[s.rangeOfComposedCharacterSequence( |
| at: s.startIndex)]) |
| expectEqual("a", s[s.rangeOfComposedCharacterSequence( |
| at: s.index(s.startIndex, offsetBy: 1))]) |
| expectEqual("\u{305f}\u{3099}", s[s.rangeOfComposedCharacterSequence( |
| at: s.index(s.startIndex, offsetBy: 5))]) |
| expectEqual(" ", s[s.rangeOfComposedCharacterSequence( |
| at: s.index(s.startIndex, offsetBy: 6))]) |
| } |
| |
| NSStringAPIs.test("rangeOfComposedCharacterSequences(for:)") { |
| let s = "\u{1F601}abc さ\u{3099}し\u{3099}す\u{3099}せ\u{3099}そ\u{3099}" |
| |
| expectEqual("\u{1F601}a", s[s.rangeOfComposedCharacterSequences( |
| for: s.startIndex..<s.index(s.startIndex, offsetBy: 2))]) |
| expectEqual("せ\u{3099}そ\u{3099}", s[s.rangeOfComposedCharacterSequences( |
| for: s.index(s.startIndex, offsetBy: 8)..<s.index(s.startIndex, offsetBy: 10))]) |
| } |
| |
| func toIntRange( |
| _ string: String, _ maybeRange: Range<String.Index>? |
| ) -> Range<Int>? { |
| guard let range = maybeRange else { return nil } |
| |
| return |
| string.distance(from: string.startIndex, to: range.lowerBound) ..< |
| string.distance(from: string.startIndex, to: range.upperBound) |
| } |
| |
| NSStringAPIs.test("range(of:options:range:locale:)") { |
| do { |
| let s = "" |
| expectEmpty(s.range(of: "")) |
| expectEmpty(s.range(of: "abc")) |
| } |
| do { |
| let s = "abc" |
| expectEmpty(s.range(of: "")) |
| expectEmpty(s.range(of: "def")) |
| expectOptionalEqual(0..<3, toIntRange(s, s.range(of: "abc"))) |
| } |
| do { |
| let s = "さ\u{3099}し\u{3099}す\u{3099}せ\u{3099}そ\u{3099}" |
| expectOptionalEqual(2..<3, toIntRange(s, s.range(of: "す\u{3099}"))) |
| expectOptionalEqual(2..<3, toIntRange(s, s.range(of: "\u{305a}"))) |
| |
| expectEmpty(s.range(of: "\u{3099}す")) |
| expectEmpty(s.range(of: "す")) |
| |
| // Note: here `rangeOf` API produces indexes that don't point between |
| // grapheme cluster boundaries -- these cannot be created with public |
| // String interface. |
| // |
| // FIXME: why does this search succeed and the above queries fail? There is |
| // no apparent pattern. |
| expectEqual("\u{3099}", s[s.range(of: "\u{3099}")!]) |
| } |
| do { |
| let s = "а\u{0301}б\u{0301}в\u{0301}г\u{0301}" |
| expectOptionalEqual(0..<1, toIntRange(s, s.range(of: "а\u{0301}"))) |
| expectOptionalEqual(1..<2, toIntRange(s, s.range(of: "б\u{0301}"))) |
| |
| expectEmpty(s.range(of: "б")) |
| expectEmpty(s.range(of: "\u{0301}б")) |
| |
| // FIXME: Again, indexes that don't correspond to grapheme |
| // cluster boundaries. |
| expectEqual("\u{0301}", s[s.range(of: "\u{0301}")!]) |
| } |
| } |
| |
| NSStringAPIs.test("contains(_:)") { |
| withOverriddenLocaleCurrentLocale("en") { () -> Void in |
| expectFalse("".contains("")) |
| expectFalse("".contains("a")) |
| expectFalse("a".contains("")) |
| expectFalse("a".contains("b")) |
| expectTrue("a".contains("a")) |
| expectFalse("a".contains("A")) |
| expectFalse("A".contains("a")) |
| expectFalse("a".contains("a\u{0301}")) |
| expectTrue("a\u{0301}".contains("a\u{0301}")) |
| expectFalse("a\u{0301}".contains("a")) |
| expectTrue("a\u{0301}".contains("\u{0301}")) |
| expectFalse("a".contains("\u{0301}")) |
| |
| expectFalse("i".contains("I")) |
| expectFalse("I".contains("i")) |
| expectFalse("\u{0130}".contains("i")) |
| expectFalse("i".contains("\u{0130}")) |
| |
| return () |
| } |
| |
| withOverriddenLocaleCurrentLocale("tr") { |
| expectFalse("\u{0130}".contains("ı")) |
| } |
| } |
| |
| NSStringAPIs.test("localizedCaseInsensitiveContains(_:)") { |
| withOverriddenLocaleCurrentLocale("en") { () -> Void in |
| expectFalse("".localizedCaseInsensitiveContains("")) |
| expectFalse("".localizedCaseInsensitiveContains("a")) |
| expectFalse("a".localizedCaseInsensitiveContains("")) |
| expectFalse("a".localizedCaseInsensitiveContains("b")) |
| expectTrue("a".localizedCaseInsensitiveContains("a")) |
| expectTrue("a".localizedCaseInsensitiveContains("A")) |
| expectTrue("A".localizedCaseInsensitiveContains("a")) |
| expectFalse("a".localizedCaseInsensitiveContains("a\u{0301}")) |
| expectTrue("a\u{0301}".localizedCaseInsensitiveContains("a\u{0301}")) |
| expectFalse("a\u{0301}".localizedCaseInsensitiveContains("a")) |
| expectTrue("a\u{0301}".localizedCaseInsensitiveContains("\u{0301}")) |
| expectFalse("a".localizedCaseInsensitiveContains("\u{0301}")) |
| |
| expectTrue("i".localizedCaseInsensitiveContains("I")) |
| expectTrue("I".localizedCaseInsensitiveContains("i")) |
| expectFalse("\u{0130}".localizedCaseInsensitiveContains("i")) |
| expectFalse("i".localizedCaseInsensitiveContains("\u{0130}")) |
| |
| return () |
| } |
| |
| withOverriddenLocaleCurrentLocale("tr") { |
| expectFalse("\u{0130}".localizedCaseInsensitiveContains("ı")) |
| } |
| } |
| |
| NSStringAPIs.test("localizedStandardContains(_:)") { |
| if #available(OSX 10.11, iOS 9.0, *) { |
| withOverriddenLocaleCurrentLocale("en") { () -> Void in |
| expectFalse("".localizedStandardContains("")) |
| expectFalse("".localizedStandardContains("a")) |
| expectFalse("a".localizedStandardContains("")) |
| expectFalse("a".localizedStandardContains("b")) |
| expectTrue("a".localizedStandardContains("a")) |
| expectTrue("a".localizedStandardContains("A")) |
| expectTrue("A".localizedStandardContains("a")) |
| expectTrue("a".localizedStandardContains("a\u{0301}")) |
| expectTrue("a\u{0301}".localizedStandardContains("a\u{0301}")) |
| expectTrue("a\u{0301}".localizedStandardContains("a")) |
| expectTrue("a\u{0301}".localizedStandardContains("\u{0301}")) |
| expectFalse("a".localizedStandardContains("\u{0301}")) |
| |
| expectTrue("i".localizedStandardContains("I")) |
| expectTrue("I".localizedStandardContains("i")) |
| expectTrue("\u{0130}".localizedStandardContains("i")) |
| expectTrue("i".localizedStandardContains("\u{0130}")) |
| |
| return () |
| } |
| |
| withOverriddenLocaleCurrentLocale("tr") { |
| expectTrue("\u{0130}".localizedStandardContains("ı")) |
| } |
| } |
| } |
| |
| NSStringAPIs.test("localizedStandardRange(of:)") { |
| if #available(OSX 10.11, iOS 9.0, *) { |
| func rangeOf(_ string: String, _ substring: String) -> Range<Int>? { |
| return toIntRange( |
| string, string.localizedStandardRange(of: substring)) |
| } |
| withOverriddenLocaleCurrentLocale("en") { () -> Void in |
| expectEmpty(rangeOf("", "")) |
| expectEmpty(rangeOf("", "a")) |
| expectEmpty(rangeOf("a", "")) |
| expectEmpty(rangeOf("a", "b")) |
| expectEqual(0..<1, rangeOf("a", "a")) |
| expectEqual(0..<1, rangeOf("a", "A")) |
| expectEqual(0..<1, rangeOf("A", "a")) |
| expectEqual(0..<1, rangeOf("a", "a\u{0301}")) |
| expectEqual(0..<1, rangeOf("a\u{0301}", "a\u{0301}")) |
| expectEqual(0..<1, rangeOf("a\u{0301}", "a")) |
| do { |
| // FIXME: Indices that don't correspond to grapheme cluster boundaries. |
| let s = "a\u{0301}" |
| expectEqual( |
| "\u{0301}", s[s.localizedStandardRange(of: "\u{0301}")!]) |
| } |
| expectEmpty(rangeOf("a", "\u{0301}")) |
| |
| expectEqual(0..<1, rangeOf("i", "I")) |
| expectEqual(0..<1, rangeOf("I", "i")) |
| expectEqual(0..<1, rangeOf("\u{0130}", "i")) |
| expectEqual(0..<1, rangeOf("i", "\u{0130}")) |
| return () |
| } |
| |
| withOverriddenLocaleCurrentLocale("tr") { |
| expectEqual(0..<1, rangeOf("\u{0130}", "ı")) |
| } |
| } |
| } |
| |
| NSStringAPIs.test("smallestEncoding") { |
| let availableEncodings: [String.Encoding] = String.availableStringEncodings |
| expectTrue(availableEncodings.contains("abc".smallestEncoding)) |
| } |
| |
| func getHomeDir() -> String { |
| #if os(OSX) |
| return String(cString: getpwuid(getuid()).pointee.pw_dir) |
| #elseif os(iOS) || os(tvOS) || os(watchOS) |
| // getpwuid() returns null in sandboxed apps under iOS simulator. |
| return NSHomeDirectory() |
| #else |
| preconditionFailed("implement") |
| #endif |
| } |
| |
| NSStringAPIs.test("addingPercentEscapes(using:)") { |
| expectEmpty( |
| "abcd абвг".addingPercentEscapes( |
| using: .ascii)) |
| expectOptionalEqual("abcd%20%D0%B0%D0%B1%D0%B2%D0%B3", |
| "abcd абвг".addingPercentEscapes( |
| using: .utf8)) |
| } |
| |
| NSStringAPIs.test("appendingFormat(_:_:...)") { |
| expectEqual("", "".appendingFormat("")) |
| expectEqual("a", "a".appendingFormat("")) |
| expectEqual( |
| "abc абв \u{0001F60A}", |
| "abc абв \u{0001F60A}".appendingFormat("")) |
| |
| let formatArg: NSString = "привет мир \u{0001F60A}" |
| expectEqual( |
| "abc абв \u{0001F60A}def привет мир \u{0001F60A} 42", |
| "abc абв \u{0001F60A}" |
| .appendingFormat("def %@ %ld", formatArg, 42)) |
| } |
| |
| NSStringAPIs.test("appending(_:)") { |
| expectEqual("", "".appending("")) |
| expectEqual("a", "a".appending("")) |
| expectEqual("a", "".appending("a")) |
| expectEqual("さ\u{3099}", "さ".appending("\u{3099}")) |
| } |
| |
| NSStringAPIs.test("folding(options:locale:)") { |
| |
| func fwo( |
| _ s: String, _ options: String.CompareOptions |
| ) -> (Locale?) -> String { |
| return { loc in s.folding(options: options, locale: loc) } |
| } |
| |
| expectLocalizedEquality("abcd", fwo("abCD", .caseInsensitive), "en") |
| |
| // U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE |
| // to lower case: |
| // U+0069 LATIN SMALL LETTER I |
| // U+0307 COMBINING DOT ABOVE |
| expectLocalizedEquality( |
| "\u{0069}\u{0307}", fwo("\u{0130}", .caseInsensitive), "en") |
| |
| // U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE |
| // to lower case in Turkish locale: |
| // U+0069 LATIN SMALL LETTER I |
| expectLocalizedEquality( |
| "\u{0069}", fwo("\u{0130}", .caseInsensitive), "tr") |
| |
| expectLocalizedEquality( |
| "example123", fwo("example123", .widthInsensitive), "en") |
| } |
| |
| NSStringAPIs.test("padding(toLength:withPad:startingAtIndex:)") { |
| expectEqual( |
| "abc абв \u{0001F60A}", |
| "abc абв \u{0001F60A}".padding( |
| toLength: 10, withPad: "XYZ", startingAt: 0)) |
| expectEqual( |
| "abc абв \u{0001F60A}XYZXY", |
| "abc абв \u{0001F60A}".padding( |
| toLength: 15, withPad: "XYZ", startingAt: 0)) |
| expectEqual( |
| "abc абв \u{0001F60A}YZXYZ", |
| "abc абв \u{0001F60A}".padding( |
| toLength: 15, withPad: "XYZ", startingAt: 1)) |
| } |
| |
| NSStringAPIs.test("removingPercentEncoding/OSX 10.9") |
| .xfail(.osxMinor(10, 9, reason: "looks like a bug in Foundation in OS X 10.9")) |
| .xfail(.iOSMajor(7, reason: "same bug in Foundation in iOS 7.*")) |
| .skip(.iOSSimulatorAny("same bug in Foundation in iOS Simulator 7.*")) |
| .code { |
| expectOptionalEqual("", "".removingPercentEncoding) |
| } |
| |
| NSStringAPIs.test("removingPercentEncoding") { |
| expectEmpty("%".removingPercentEncoding) |
| expectOptionalEqual( |
| "abcd абвг", |
| "ab%63d %D0%B0%D0%B1%D0%B2%D0%B3".removingPercentEncoding) |
| } |
| |
| NSStringAPIs.test("replacingCharacters(in:with:)") { |
| do { |
| let empty = "" |
| expectEqual("", empty.replacingCharacters( |
| in: empty.startIndex..<empty.startIndex, with: "")) |
| } |
| |
| let s = "\u{1F601}abc さ\u{3099}し\u{3099}す\u{3099}せ\u{3099}そ\u{3099}" |
| |
| expectEqual(s, s.replacingCharacters( |
| in: s.startIndex..<s.startIndex, with: "")) |
| expectEqual(s, s.replacingCharacters( |
| in: s.endIndex..<s.endIndex, with: "")) |
| expectEqual("zzz" + s, s.replacingCharacters( |
| in: s.startIndex..<s.startIndex, with: "zzz")) |
| expectEqual(s + "zzz", s.replacingCharacters( |
| in: s.endIndex..<s.endIndex, with: "zzz")) |
| |
| expectEqual( |
| "す\u{3099}せ\u{3099}そ\u{3099}", |
| s.replacingCharacters( |
| in: s.startIndex..<s.index(s.startIndex, offsetBy: 7), with: "")) |
| expectEqual( |
| "zzzす\u{3099}せ\u{3099}そ\u{3099}", |
| s.replacingCharacters( |
| in: s.startIndex..<s.index(s.startIndex, offsetBy: 7), with: "zzz")) |
| expectEqual( |
| "\u{1F602}す\u{3099}せ\u{3099}そ\u{3099}", |
| s.replacingCharacters( |
| in: s.startIndex..<s.index(s.startIndex, offsetBy: 7), with: "\u{1F602}")) |
| |
| expectEqual("\u{1F601}", s.replacingCharacters( |
| in: s.index(after: s.startIndex)..<s.endIndex, with: "")) |
| expectEqual("\u{1F601}zzz", s.replacingCharacters( |
| in: s.index(after: s.startIndex)..<s.endIndex, with: "zzz")) |
| expectEqual("\u{1F601}\u{1F602}", s.replacingCharacters( |
| in: s.index(after: s.startIndex)..<s.endIndex, with: "\u{1F602}")) |
| |
| expectEqual( |
| "\u{1F601}aす\u{3099}せ\u{3099}そ\u{3099}", |
| s.replacingCharacters( |
| in: s.index(s.startIndex, offsetBy: 2)..<s.index(s.startIndex, offsetBy: 7), with: "")) |
| expectEqual( |
| "\u{1F601}azzzす\u{3099}せ\u{3099}そ\u{3099}", |
| s.replacingCharacters( |
| in: s.index(s.startIndex, offsetBy: 2)..<s.index(s.startIndex, offsetBy: 7), with: "zzz")) |
| expectEqual( |
| "\u{1F601}a\u{1F602}す\u{3099}せ\u{3099}そ\u{3099}", |
| s.replacingCharacters( |
| in: s.index(s.startIndex, offsetBy: 2)..<s.index(s.startIndex, offsetBy: 7), |
| with: "\u{1F602}")) |
| } |
| |
| NSStringAPIs.test("replacingOccurrences(of:with:options:range:)") { |
| do { |
| let empty = "" |
| expectEqual("", empty.replacingOccurrences( |
| of: "", with: "")) |
| expectEqual("", empty.replacingOccurrences( |
| of: "", with: "xyz")) |
| expectEqual("", empty.replacingOccurrences( |
| of: "abc", with: "xyz")) |
| } |
| |
| let s = "\u{1F601}abc さ\u{3099}し\u{3099}す\u{3099}せ\u{3099}そ\u{3099}" |
| |
| expectEqual(s, s.replacingOccurrences(of: "", with: "xyz")) |
| expectEqual(s, s.replacingOccurrences(of: "xyz", with: "")) |
| |
| expectEqual("", s.replacingOccurrences(of: s, with: "")) |
| |
| expectEqual( |
| "\u{1F601}xyzbc さ\u{3099}し\u{3099}す\u{3099}せ\u{3099}そ\u{3099}", |
| s.replacingOccurrences(of: "a", with: "xyz")) |
| |
| expectEqual( |
| "\u{1F602}\u{1F603}abc さ\u{3099}し\u{3099}す\u{3099}せ\u{3099}そ\u{3099}", |
| s.replacingOccurrences( |
| of: "\u{1F601}", with: "\u{1F602}\u{1F603}")) |
| |
| expectEqual( |
| "\u{1F601}abc さ\u{3099}xyzす\u{3099}せ\u{3099}そ\u{3099}", |
| s.replacingOccurrences( |
| of: "し\u{3099}", with: "xyz")) |
| |
| expectEqual( |
| "\u{1F601}abc さ\u{3099}xyzす\u{3099}せ\u{3099}そ\u{3099}", |
| s.replacingOccurrences( |
| of: "し\u{3099}", with: "xyz")) |
| |
| expectEqual( |
| "\u{1F601}abc さ\u{3099}xyzす\u{3099}せ\u{3099}そ\u{3099}", |
| s.replacingOccurrences( |
| of: "\u{3058}", with: "xyz")) |
| |
| // |
| // Use non-default 'options:' |
| // |
| |
| expectEqual( |
| "\u{1F602}\u{1F603}abc さ\u{3099}し\u{3099}す\u{3099}せ\u{3099}そ\u{3099}", |
| s.replacingOccurrences( |
| of: "\u{1F601}", with: "\u{1F602}\u{1F603}", |
| options: String.CompareOptions.literal)) |
| |
| expectEqual(s, s.replacingOccurrences( |
| of: "\u{3058}", with: "xyz", |
| options: String.CompareOptions.literal)) |
| |
| // |
| // Use non-default 'range:' |
| // |
| |
| expectEqual( |
| "\u{1F602}\u{1F603}abc さ\u{3099}し\u{3099}す\u{3099}せ\u{3099}そ\u{3099}", |
| s.replacingOccurrences( |
| of: "\u{1F601}", with: "\u{1F602}\u{1F603}", |
| options: String.CompareOptions.literal, |
| range: s.startIndex..<s.index(s.startIndex, offsetBy: 1))) |
| |
| expectEqual(s, s.replacingOccurrences( |
| of: "\u{1F601}", with: "\u{1F602}\u{1F603}", |
| options: String.CompareOptions.literal, |
| range: s.index(s.startIndex, offsetBy: 1)..<s.index(s.startIndex, offsetBy: 3))) |
| } |
| |
| NSStringAPIs.test("replacingPercentEscapes(using:)") { |
| expectOptionalEqual( |
| "abcd абвг", |
| "abcd абвг".replacingPercentEscapes( |
| using: .ascii)) |
| |
| expectOptionalEqual( |
| "abcd абвг\u{0000}\u{0001}", |
| "abcd абвг%00%01".replacingPercentEscapes( |
| using: .ascii)) |
| |
| expectOptionalEqual( |
| "abcd абвг", |
| "%61%62%63%64%20%D0%B0%D0%B1%D0%B2%D0%B3" |
| .replacingPercentEscapes(using: .utf8)) |
| |
| expectEmpty("%ED%B0".replacingPercentEscapes( |
| using: .utf8)) |
| |
| expectEmpty("%zz".replacingPercentEscapes( |
| using: .utf8)) |
| } |
| |
| NSStringAPIs.test("replacingPercentEscapes(using:)/rdar18029471") |
| .xfail( |
| .custom({ true }, |
| reason: "<rdar://problem/18029471> NSString " + |
| "replacingPercentEscapesUsingEncoding: does not return nil " + |
| "when a byte sequence is not legal in ASCII")) |
| .code { |
| expectEmpty( |
| "abcd%FF".replacingPercentEscapes( |
| using: .ascii)) |
| } |
| |
| NSStringAPIs.test("trimmingCharacters(in:)") { |
| expectEqual("", "".trimmingCharacters( |
| in: CharacterSet.decimalDigits)) |
| |
| expectEqual("abc", "abc".trimmingCharacters( |
| in: CharacterSet.decimalDigits)) |
| |
| expectEqual("", "123".trimmingCharacters( |
| in: CharacterSet.decimalDigits)) |
| |
| expectEqual("abc", "123abc789".trimmingCharacters( |
| in: CharacterSet.decimalDigits)) |
| |
| // Performs Unicode scalar comparison. |
| expectEqual( |
| "し\u{3099}abc", |
| "し\u{3099}abc".trimmingCharacters( |
| in: CharacterSet(charactersIn: "\u{3058}"))) |
| } |
| |
| NSStringAPIs.test("NSString.stringsByAppendingPaths(_:)") { |
| expectEqual([] as [NSString], ("" as NSString).strings(byAppendingPaths: []) as [NSString]) |
| expectEqual( |
| [ "/tmp/foo", "/tmp/bar" ] as [NSString], |
| ("/tmp" as NSString).strings(byAppendingPaths: [ "foo", "bar" ]) as [NSString]) |
| } |
| |
| NSStringAPIs.test("substring(from:)") { |
| let s = "\u{1F601}abc さ\u{3099}し\u{3099}す\u{3099}せ\u{3099}そ\u{3099}" |
| |
| expectEqual(s, s.substring(from: s.startIndex)) |
| expectEqual("せ\u{3099}そ\u{3099}", |
| s.substring(from: s.index(s.startIndex, offsetBy: 8))) |
| expectEqual("", s.substring(from: s.index(s.startIndex, offsetBy: 10))) |
| } |
| |
| NSStringAPIs.test("substring(to:)") { |
| let s = "\u{1F601}abc さ\u{3099}し\u{3099}す\u{3099}せ\u{3099}そ\u{3099}" |
| |
| expectEqual("", s.substring(to: s.startIndex)) |
| expectEqual("\u{1F601}abc さ\u{3099}し\u{3099}す\u{3099}", |
| s.substring(to: s.index(s.startIndex, offsetBy: 8))) |
| expectEqual(s, s.substring(to: s.index(s.startIndex, offsetBy: 10))) |
| } |
| |
| NSStringAPIs.test("substring(with:)") { |
| let s = "\u{1F601}abc さ\u{3099}し\u{3099}す\u{3099}せ\u{3099}そ\u{3099}" |
| |
| expectEqual("", s.substring(with: s.startIndex..<s.startIndex)) |
| expectEqual( |
| "", |
| s.substring(with: s.index(s.startIndex, offsetBy: 1)..<s.index(s.startIndex, offsetBy: 1))) |
| expectEqual("", s.substring(with: s.endIndex..<s.endIndex)) |
| expectEqual(s, s.substring(with: s.startIndex..<s.endIndex)) |
| expectEqual( |
| "さ\u{3099}し\u{3099}す\u{3099}", |
| s.substring(with: s.index(s.startIndex, offsetBy: 5)..<s.index(s.startIndex, offsetBy: 8))) |
| } |
| |
| NSStringAPIs.test("localizedUppercase") { |
| if #available(OSX 10.11, iOS 9.0, *) { |
| withOverriddenLocaleCurrentLocale("en") { |
| expectEqual("ABCD", "abCD".localizedUppercase) |
| } |
| |
| withOverriddenLocaleCurrentLocale("en") { |
| expectEqual("АБВГ", "абВГ".localizedUppercase) |
| } |
| |
| withOverriddenLocaleCurrentLocale("ru") { |
| expectEqual("АБВГ", "абВГ".localizedUppercase) |
| } |
| |
| withOverriddenLocaleCurrentLocale("ru") { |
| expectEqual("たちつてと", "たちつてと".localizedUppercase) |
| } |
| |
| // |
| // Special casing. |
| // |
| |
| // U+0069 LATIN SMALL LETTER I |
| // to upper case: |
| // U+0049 LATIN CAPITAL LETTER I |
| withOverriddenLocaleCurrentLocale("en") { |
| expectEqual("\u{0049}", "\u{0069}".localizedUppercase) |
| } |
| |
| // U+0069 LATIN SMALL LETTER I |
| // to upper case in Turkish locale: |
| // U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE |
| withOverriddenLocaleCurrentLocale("tr") { |
| expectEqual("\u{0130}", "\u{0069}".localizedUppercase) |
| } |
| |
| // U+00DF LATIN SMALL LETTER SHARP S |
| // to upper case: |
| // U+0053 LATIN CAPITAL LETTER S |
| // U+0073 LATIN SMALL LETTER S |
| // But because the whole string is converted to uppercase, we just get two |
| // U+0053. |
| withOverriddenLocaleCurrentLocale("en") { |
| expectEqual("\u{0053}\u{0053}", "\u{00df}".localizedUppercase) |
| } |
| |
| // U+FB01 LATIN SMALL LIGATURE FI |
| // to upper case: |
| // U+0046 LATIN CAPITAL LETTER F |
| // U+0069 LATIN SMALL LETTER I |
| // But because the whole string is converted to uppercase, we get U+0049 |
| // LATIN CAPITAL LETTER I. |
| withOverriddenLocaleCurrentLocale("ru") { |
| expectEqual("\u{0046}\u{0049}", "\u{fb01}".localizedUppercase) |
| } |
| } |
| } |
| |
| NSStringAPIs.test("uppercased(with:)") { |
| expectLocalizedEquality("ABCD", { loc in "abCD".uppercased(with: loc) }, "en") |
| |
| expectLocalizedEquality("АБВГ", { loc in "абВГ".uppercased(with: loc) }, "en") |
| expectLocalizedEquality("АБВГ", { loc in "абВГ".uppercased(with: loc) }, "ru") |
| |
| expectLocalizedEquality("たちつてと", { loc in "たちつてと".uppercased(with: loc) }, "ru") |
| |
| // |
| // Special casing. |
| // |
| |
| // U+0069 LATIN SMALL LETTER I |
| // to upper case: |
| // U+0049 LATIN CAPITAL LETTER I |
| expectLocalizedEquality("\u{0049}", { loc in "\u{0069}".uppercased(with: loc) }, "en") |
| |
| // U+0069 LATIN SMALL LETTER I |
| // to upper case in Turkish locale: |
| // U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE |
| expectLocalizedEquality("\u{0130}", { loc in "\u{0069}".uppercased(with: loc) }, "tr") |
| |
| // U+00DF LATIN SMALL LETTER SHARP S |
| // to upper case: |
| // U+0053 LATIN CAPITAL LETTER S |
| // U+0073 LATIN SMALL LETTER S |
| // But because the whole string is converted to uppercase, we just get two |
| // U+0053. |
| expectLocalizedEquality("\u{0053}\u{0053}", { loc in "\u{00df}".uppercased(with: loc) }, "en") |
| |
| // U+FB01 LATIN SMALL LIGATURE FI |
| // to upper case: |
| // U+0046 LATIN CAPITAL LETTER F |
| // U+0069 LATIN SMALL LETTER I |
| // But because the whole string is converted to uppercase, we get U+0049 |
| // LATIN CAPITAL LETTER I. |
| expectLocalizedEquality("\u{0046}\u{0049}", { loc in "\u{fb01}".uppercased(with: loc) }, "ru") |
| } |
| |
| NSStringAPIs.test("write(toFile:atomically:encoding:error:)") { |
| let (_, nonExistentPath) = createNSStringTemporaryFile() |
| do { |
| let s = "Lorem ipsum dolor sit amet, consectetur adipisicing elit" |
| try s.write( |
| toFile: nonExistentPath, atomically: false, encoding: .ascii) |
| |
| let content = try String( |
| contentsOfFile: nonExistentPath, encoding: .ascii) |
| |
| expectEqual(s, content) |
| } catch { |
| expectUnreachableCatch(error) |
| } |
| } |
| |
| NSStringAPIs.test("write(to:atomically:encoding:error:)") { |
| let (_, nonExistentPath) = createNSStringTemporaryFile() |
| let nonExistentURL = URL(string: "file://" + nonExistentPath)! |
| do { |
| let s = "Lorem ipsum dolor sit amet, consectetur adipisicing elit" |
| try s.write( |
| to: nonExistentURL, atomically: false, encoding: .ascii) |
| |
| let content = try String( |
| contentsOfFile: nonExistentPath, encoding: .ascii) |
| |
| expectEqual(s, content) |
| } catch { |
| expectUnreachableCatch(error) |
| } |
| } |
| |
| NSStringAPIs.test("applyingTransform(_:reverse:)") { |
| if #available(OSX 10.11, iOS 9.0, *) { |
| do { |
| let source = "tre\u{300}s k\u{fc}hl" |
| expectEqual( |
| "tres kuhl", |
| source.applyingTransform(.stripDiacritics, reverse: false)) |
| } |
| do { |
| let source = "hiragana" |
| expectEqual( |
| "ひらがな", |
| source.applyingTransform(.latinToHiragana, reverse: false)) |
| } |
| do { |
| let source = "ひらがな" |
| expectEqual( |
| "hiragana", |
| source.applyingTransform(.latinToHiragana, reverse: true)) |
| } |
| } |
| } |
| |
| NSStringAPIs.test("SameTypeComparisons") { |
| // U+0323 COMBINING DOT BELOW |
| // U+0307 COMBINING DOT ABOVE |
| // U+1E63 LATIN SMALL LETTER S WITH DOT BELOW |
| let xs = "\u{1e69}" |
| expectTrue(xs == "s\u{323}\u{307}") |
| expectFalse(xs != "s\u{323}\u{307}") |
| expectTrue("s\u{323}\u{307}" == xs) |
| expectFalse("s\u{323}\u{307}" != xs) |
| expectTrue("\u{1e69}" == "s\u{323}\u{307}") |
| expectFalse("\u{1e69}" != "s\u{323}\u{307}") |
| expectTrue(xs == xs) |
| expectFalse(xs != xs) |
| } |
| |
| NSStringAPIs.test("MixedTypeComparisons") { |
| // U+0323 COMBINING DOT BELOW |
| // U+0307 COMBINING DOT ABOVE |
| // U+1E63 LATIN SMALL LETTER S WITH DOT BELOW |
| // NSString does not decompose characters, so the two strings will be (==) in |
| // swift but not in Foundation. |
| let xs = "\u{1e69}" |
| let ys: NSString = "s\u{323}\u{307}" |
| expectFalse(ys == "\u{1e69}") |
| expectTrue(ys != "\u{1e69}") |
| expectFalse("\u{1e69}" == ys) |
| expectTrue("\u{1e69}" != ys) |
| expectFalse(xs as NSString == ys) |
| expectTrue(xs as NSString != ys) |
| expectTrue(ys == ys) |
| expectFalse(ys != ys) |
| } |
| |
| NSStringAPIs.test("CompareStringsWithUnpairedSurrogates") |
| .xfail( |
| .custom({ true }, |
| reason: "<rdar://problem/18029104> Strings referring to underlying " + |
| "storage with unpaired surrogates compare unequal")) |
| .code { |
| let donor = "abcdef" |
| let acceptor = "\u{1f601}\u{1f602}\u{1f603}" |
| |
| expectEqual("\u{fffd}\u{1f602}\u{fffd}", |
| acceptor[donor.index(donor.startIndex, offsetBy: 1)..<donor.index(donor.startIndex, offsetBy: 5)]) |
| } |
| |
| NSStringAPIs.test("copy construction") { |
| let expected = "abcd" |
| let x = NSString(string: expected as NSString) |
| expectEqual(expected, x as String) |
| let y = NSMutableString(string: expected as NSString) |
| expectEqual(expected, y as String) |
| } |
| |
| runAllTests() |
| |