// 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.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).., sentenceRange: Range, 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.., enclosingRange: Range, 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.., enclosingRange: Range, 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..] = [] var tags = s.linguisticTags(in: startIndex.. 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) } 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)..? ) -> Range? { 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? { 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("appendingPathComponent(_:)") { expectEqual("", "".appendingPathComponent("")) expectEqual("a.txt", "".appendingPathComponent("a.txt")) expectEqual("/tmp/a.txt", "/tmp".appendingPathComponent("a.txt")) } NSStringAPIs.test("appending(_:)") { expectEqual("", "".appending("")) expectEqual("a", "a".appending("")) expectEqual("a", "".appending("a")) expectEqual("さ\u{3099}", "さ".appending("\u{3099}")) } NSStringAPIs.test("deletingLastPathComponent") { expectEqual("", "".deletingLastPathComponent) expectEqual("/", "/".deletingLastPathComponent) expectEqual("/", "/tmp".deletingLastPathComponent) expectEqual("/tmp", "/tmp/a.txt".deletingLastPathComponent) } 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.. NSString " + "replacingPercentEscapesUsingEncoding: does not return nil " + "when a byte sequence is not legal in ASCII")) .code { expectEmpty( "abcd%FF".replacingPercentEscapes( using: .ascii)) } NSStringAPIs.test("resolvingSymlinksInPath") { // Difference between // resolvingSymlinksInPath and stringByStandardizingPath is unclear expectEqual("", "".resolvingSymlinksInPath) expectEqual( "/var", "/private/var/tmp////..//".resolvingSymlinksInPath) } NSStringAPIs.test("standardizingPath") { // Difference between // resolvingSymlinksInPath and standardizingPath is unclear expectEqual("", "".standardizingPath) expectEqual( "/var", "/private/var/tmp////..//".standardizingPath) } 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.. 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)..