// RUN: rm -rf %t // RUN: mkdir -p %t // RUN: %target-build-swift %s -o %t/a.out // RUN: %target-run %t/a.out // REQUIRES: executable_test // REQUIRES: objc_interop // // Tests for the NSString APIs as exposed by String // import StdlibUnittest // Also import modules which are used by StdlibUnittest internally. This // workaround is needed to link all required libraries in case we compile // StdlibUnittest with -sil-serialize-all. import SwiftPrivate #if _runtime(_ObjC) import ObjectiveC #endif 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) -> AnyObject { // 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: [NSStringEncoding] = String.availableStringEncodings() expectNotEqual(0, availableEncodings.count) let defaultCStringEncoding = String.defaultCStringEncoding() expectTrue(availableEncodings.contains(defaultCStringEncoding)) expectNotEqual("", String.localizedName(ofStringEncoding: NSUTF8StringEncoding)) } NSStringAPIs.test("NSStringEncoding") { // Make sure NSStringEncoding and its values are type-compatible. var enc: NSStringEncoding enc = NSWindowsCP1250StringEncoding enc = NSUTF32LittleEndianStringEncoding enc = NSUTF32BigEndianStringEncoding enc = NSASCIIStringEncoding enc = NSUTF8StringEncoding } NSStringAPIs.test("localizedStringWithFormat(_:...)") { var world: NSString = "world" expectEqual("Hello, world!%42", String.localizedStringWithFormat( "Hello, %@!%%%ld", world, 42)) withOverriddenNSLocaleCurrentLocale("en_US") { expectEqual("0.5", String.localizedStringWithFormat("%g", 0.5)) } withOverriddenNSLocaleCurrentLocale("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: NSASCIIStringEncoding) expectEqual( "Lorem ipsum dolor sit amet, consectetur adipisicing elit,", content._lines[0]) } catch { expectUnreachableCatch(error) } do { let content = try String( contentsOfFile: nonExistentPath, encoding: NSASCIIStringEncoding) expectUnreachable() } catch { } } NSStringAPIs.test("init(contentsOfFile:usedEncoding:error:)") { let (existingPath, nonExistentPath) = createNSStringTemporaryFile() do { var usedEncoding: NSStringEncoding = 0 let content = try String( contentsOfFile: existingPath, usedEncoding: &usedEncoding) expectNotEqual(0, usedEncoding) expectEqual( "Lorem ipsum dolor sit amet, consectetur adipisicing elit,", content._lines[0]) } catch { expectUnreachableCatch(error) } var usedEncoding: NSStringEncoding = 0 do { _ = try String(contentsOfFile: nonExistentPath) expectUnreachable() } catch { expectEqual(0, usedEncoding) } } NSStringAPIs.test("init(contentsOf:encoding:error:)") { let (existingPath, nonExistentPath) = createNSStringTemporaryFile() let existingURL = NSURL(string: "file://" + existingPath)! let nonExistentURL = NSURL(string: "file://" + nonExistentPath)! do { let content = try String( contentsOf: existingURL, encoding: NSASCIIStringEncoding) expectEqual( "Lorem ipsum dolor sit amet, consectetur adipisicing elit,", content._lines[0]) } catch { expectUnreachableCatch(error) } do { _ = try String(contentsOf: nonExistentURL, encoding: NSASCIIStringEncoding) expectUnreachable() } catch { } } NSStringAPIs.test("init(contentsOf:usedEncoding:error:)") { let (existingPath, nonExistentPath) = createNSStringTemporaryFile() let existingURL = NSURL(string: "file://" + existingPath)! let nonExistentURL = NSURL(string: "file://" + nonExistentPath)! do { var usedEncoding: NSStringEncoding = 0 let content = try String( contentsOf: existingURL, usedEncoding: &usedEncoding) expectNotEqual(0, usedEncoding) expectEqual( "Lorem ipsum dolor sit amet, consectetur adipisicing elit,", content._lines[0]) } catch { expectUnreachableCatch(error) } var usedEncoding: NSStringEncoding = 0 do { _ = try String(contentsOf: nonExistentURL, usedEncoding: &usedEncoding) expectUnreachable() } catch { expectEqual(0, usedEncoding) } } 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(allocatingCapacity: 100) var i = 0 for b in s.utf8 { up[i] = b i += 1 } up[i] = 0 expectOptionalEqual(s, String(utf8String: UnsafePointer(up))) up.deallocateCapacity(100) } NSStringAPIs.test("canBeConvertedToEncoding(_:)") { expectTrue("foo".canBeConverted(toEncoding: NSASCIIStringEncoding)) expectFalse("あいう".canBeConverted(toEncoding: NSASCIIStringEncoding)) } 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, *) { withOverriddenNSLocaleCurrentLocale("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 withOverriddenNSLocaleCurrentLocale("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 withOverriddenNSLocaleCurrentLocale("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: (_: NSLocale?) -> String, _ localeID: String? = nil, @autoclosure _ message: () -> 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 { NSLocale(localeIdentifier: $0) } ?? NSLocale.current() expectEqual( expected, op(locale), message(), stackTrace: trace) expectEqual( op(NSLocale.system()), op(nil), message(), stackTrace: trace) } NSStringAPIs.test("capitalizedString(with:)") { expectLocalizedEquality( "Foo Foo Foo Foo", { loc in "foo Foo fOO FOO".capitalizedString(with: loc) }) expectLocalizedEquality("Жжж", { loc in "жжж".capitalizedString(with: loc) }) expectEqual( "Foo Foo Foo Foo", "foo Foo fOO FOO".capitalizedString(with: nil)) expectEqual("Жжж", "жжж".capitalizedString(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".capitalizedString(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".capitalizedString(with: loc) }, "tr") } NSStringAPIs.test("caseInsensitiveCompare(_:)") { expectEqual(NSComparisonResult.orderedSame, "abCD".caseInsensitiveCompare("AbCd")) expectEqual(NSComparisonResult.orderedAscending, "abCD".caseInsensitiveCompare("AbCdE")) expectEqual(NSComparisonResult.orderedSame, "абвг".caseInsensitiveCompare("АбВг")) expectEqual(NSComparisonResult.orderedAscending, "абВГ".caseInsensitiveCompare("АбВгД")) } NSStringAPIs.test("commonPrefix(with:options:)") { expectEqual("ab", "abcd".commonPrefix(with: "abdc", options: [])) expectEqual("abC", "abCd".commonPrefix(with: "abce", options: .caseInsensitiveSearch)) expectEqual("аб", "абвг".commonPrefix(with: "абгв", options: [])) expectEqual("абВ", "абВг".commonPrefix(with: "абвд", options: .caseInsensitiveSearch)) } NSStringAPIs.test("compare(_:options:range:locale:)") { expectEqual(NSComparisonResult.orderedSame, "abc".compare("abc")) expectEqual(NSComparisonResult.orderedAscending, "абв".compare("где")) expectEqual(NSComparisonResult.orderedSame, "abc".compare("abC", options: .caseInsensitiveSearch)) expectEqual(NSComparisonResult.orderedSame, "абв".compare("абВ", options: .caseInsensitiveSearch)) do { let s = "abcd" let r = s.startIndex.successor()..(data!.bytes), count: data!.length)) let expectedBytes: [UInt8] = [ 0xe3, 0x81, 0x82, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x86 ] expectEqualSequence(expectedBytes, bytes) } } NSStringAPIs.test("init(data:encoding:)") { let bytes: [UInt8] = [0xe3, 0x81, 0x82, 0xe3, 0x81, 0x84, 0xe3, 0x81, 0x86] let data = NSData(bytes: bytes, length: bytes.count) expectEmpty(String(data: data, encoding: NSNonLossyASCIIStringEncoding)) expectEqualSequence( "あいう".characters, String(data: data, encoding: NSUTF8StringEncoding)!.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.startIndex.advanced(by: 5) let endIndex = s.startIndex.advanced(by: 62) var tags: [String] = [] var tokens: [String] = [] var sentences: [String] = [] s.enumerateLinguisticTags(in: 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: [NSStringEncoding] = 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.startIndex.advanced(by: 8) let endIndex = s.startIndex.advanced(by: 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 = NSCharacterSet(charactersIn: "абв") do { let s = "Глокая куздра" let r = s.rangeOfCharacter(from: charset)! expectEqual(s.startIndex.advanced(by: 4), r.startIndex) expectEqual(s.startIndex.advanced(by: 5), r.endIndex) } do { expectEmpty("клмн".rangeOfCharacter(from: charset)) } do { let s = "абвклмнабвклмн" let r = s.rangeOfCharacter(from: charset, options: .backwardsSearch)! expectEqual(s.startIndex.advanced(by: 9), r.startIndex) expectEqual(s.startIndex.advanced(by: 10), r.endIndex) } do { let s = "абвклмнабв" let r = s.rangeOfCharacter(from: charset, range: s.startIndex.advanced(by: 3)..? ) -> Range? { guard let range = maybeRange else { return nil } return string.startIndex.distance(to: range.startIndex) ..< string.startIndex.distance(to: range.endIndex) } 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(_:)") { withOverriddenNSLocaleCurrentLocale("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 () } withOverriddenNSLocaleCurrentLocale("tr") { expectFalse("\u{0130}".contains("ı")) } } NSStringAPIs.test("localizedCaseInsensitiveContains(_:)") { withOverriddenNSLocaleCurrentLocale("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 () } withOverriddenNSLocaleCurrentLocale("tr") { expectFalse("\u{0130}".localizedCaseInsensitiveContains("ı")) } } NSStringAPIs.test("localizedStandardContains(_:)") { if #available(OSX 10.11, iOS 9.0, *) { withOverriddenNSLocaleCurrentLocale("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 () } withOverriddenNSLocaleCurrentLocale("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)) } withOverriddenNSLocaleCurrentLocale("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 () } withOverriddenNSLocaleCurrentLocale("tr") { expectEqual(0..<1, rangeOf("\u{0130}", "ı")) } } } NSStringAPIs.test("smallestEncoding") { let availableEncodings: [NSStringEncoding] = 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(usingEncoding:)") { expectEmpty( "abcd абвг".addingPercentEscapes( usingEncoding: NSASCIIStringEncoding)) expectOptionalEqual("abcd%20%D0%B0%D0%B1%D0%B2%D0%B3", "abcd абвг".addingPercentEscapes( usingEncoding: NSUTF8StringEncoding)) } 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(_:locale:)") { func fwo( s: String, _ options: NSStringCompareOptions ) -> (NSLocale?) -> String { return { loc in s.folding(options, locale: loc) } } expectLocalizedEquality("abcd", fwo("abCD", .caseInsensitiveSearch), "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}", .caseInsensitiveSearch), "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}", .caseInsensitiveSearch), "tr") expectLocalizedEquality( "example123", fwo("example123", .widthInsensitiveSearch), "en") } NSStringAPIs.test("padding(toLength:with:startingAtIndex:)") { expectEqual( "abc абв \u{0001F60A}", "abc абв \u{0001F60A}".padding( toLength: 10, with: "XYZ", startingAt: 0)) expectEqual( "abc абв \u{0001F60A}XYZXY", "abc абв \u{0001F60A}".padding( toLength: 15, with: "XYZ", startingAt: 0)) expectEqual( "abc абв \u{0001F60A}YZXYZ", "abc абв \u{0001F60A}".padding( toLength: 15, with: "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( usingEncoding: NSASCIIStringEncoding)) } 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: NSCharacterSet.decimalDigit())) expectEqual("abc", "abc".trimmingCharacters( in: NSCharacterSet.decimalDigit())) expectEqual("", "123".trimmingCharacters( in: NSCharacterSet.decimalDigit())) expectEqual("abc", "123abc789".trimmingCharacters( in: NSCharacterSet.decimalDigit())) // Performs Unicode scalar comparison. expectEqual( "し\u{3099}abc", "し\u{3099}abc".trimmingCharacters( in: NSCharacterSet(charactersIn: "\u{3058}"))) } NSStringAPIs.test("NSString.stringsByAppendingPaths(_:)") { expectEqual([], "".strings(byAppendingPaths: [])) expectEqual( [ "/tmp/foo", "/tmp/bar" ], "/tmp".strings(byAppendingPaths: [ "foo", "bar" ])) } 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.startIndex.advanced(by: 8))) expectEqual("", s.substring(from: s.startIndex.advanced(by: 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.startIndex.advanced(by: 8))) expectEqual(s, s.substring(to: s.startIndex.advanced(by: 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.startIndex.advanced(by: 1)..