// RUN: rm -rf %t // RUN: mkdir -p %t // RUN: %target-build-swift -module-cache-path %t/clang-module-cache %s -o %t/a.out // RUN: %target-run %t/a.out %S/Inputs/NSStringAPI_test.txt | FileCheck %s // // Tests for the NSString APIs as exposed by String // import StdlibUnittest import Foundation // 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") } init(_ value: [UInt16]) { _value = value super.init() } @objc override func copyWithZone(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 characterAtIndex(index: Int) -> unichar { return _value[index] } var _value: [UInt16] } var NSStringAPIs = TestCase("NSStringAPIs") NSStringAPIs.test("Encodings") { let availableEncodings: [NSStringEncoding] = String.availableStringEncodings() expectNotEqual(0, availableEncodings.count) let defaultCStringEncoding = String.defaultCStringEncoding() expectTrue(contains(availableEncodings, defaultCStringEncoding)) expectNotEqual("", String.localizedNameOfStringEncoding(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)) } NSStringAPIs.test("pathWithComponents(_:)") { expectEqual("flugelhorn/baritone/bass", String.pathWithComponents(["flugelhorn", "baritone", "bass"])) } var existingPath = Process.arguments[1] var nonExistentPath = existingPath + "-NoNeXiStEnT" NSStringAPIs.test("stringWithContentsOfFile(_:encoding:error:)") { if true { var err: NSError? var content = String.stringWithContentsOfFile(existingPath, encoding: NSASCIIStringEncoding, error: &err) expectEmpty(err) expectOptionalEqual( "Lorem ipsum dolor sit amet, consectetur adipisicing elit,", content?._lines[0]) } if true { var err: NSError? var content = String.stringWithContentsOfFile(nonExistentPath, encoding: NSASCIIStringEncoding, error: &err) expectNotEmpty(err) expectEmpty(content) } } NSStringAPIs.test("stringWithContentsOfFile(_:usedEncoding:error:)") { if true { var usedEncoding: NSStringEncoding = 0 var err: NSError? var content = String.stringWithContentsOfFile(existingPath, usedEncoding: &usedEncoding, error: &err) expectNotEqual(0, usedEncoding) expectEmpty(err) expectOptionalEqual( "Lorem ipsum dolor sit amet, consectetur adipisicing elit,", content?._lines[0]) } if true { var usedEncoding: NSStringEncoding = 0 var err: NSError? var content = String.stringWithContentsOfFile(nonExistentPath, error: &err) expectEqual(0, usedEncoding) expectNotEmpty(err) expectEmpty(content) } } var existingURL = NSURL.URLWithString("file://" + existingPath) var nonExistentURL = NSURL.URLWithString("file://" + nonExistentPath) NSStringAPIs.test("stringWithContentsOfURL(_:encoding:error:)") { if true { var err: NSError? var content = String.stringWithContentsOfURL(existingURL, encoding: NSASCIIStringEncoding, error: &err) expectEmpty(err) expectOptionalEqual( "Lorem ipsum dolor sit amet, consectetur adipisicing elit,", content?._lines[0]) } if true { var err: NSError? var content = String.stringWithContentsOfURL(nonExistentURL, encoding: NSASCIIStringEncoding, error: &err) expectNotEmpty(err) expectEmpty(content) } } NSStringAPIs.test("stringWithContentsOfURL(_:usedEncoding:error:)") { if true { var usedEncoding: NSStringEncoding = 0 var err: NSError? var content = String.stringWithContentsOfURL(existingURL, usedEncoding: &usedEncoding, error: &err) expectNotEqual(0, usedEncoding) expectEmpty(err) expectOptionalEqual( "Lorem ipsum dolor sit amet, consectetur adipisicing elit,", content?._lines[0]) } if true { var usedEncoding: NSStringEncoding = 0 var err: NSError? var content = String.stringWithContentsOfURL(nonExistentURL, usedEncoding: &usedEncoding, error: &err) expectEqual(0, usedEncoding) expectNotEmpty(err) expectEmpty(content) } } NSStringAPIs.test("stringWithCString(_:encoding:)") { expectOptionalEqual("foo, a basmati bar!", String.stringWithCString( "foo, a basmati bar!", encoding: String.defaultCStringEncoding())) } NSStringAPIs.test("stringWithUTF8String(_:)") { var s = "foo あいう" var up = UnsafeMutablePointer.alloc(100) var i = 0 for b in s.utf8 { up[i] = b i++ } up[i] = 0 expectOptionalEqual(s, String.stringWithUTF8String(UnsafePointer(up))) up.dealloc(100) } NSStringAPIs.test("canBeConvertedToEncoding(_:)") { expectTrue("foo".canBeConvertedToEncoding(NSASCIIStringEncoding)) expectFalse("あいう".canBeConvertedToEncoding(NSASCIIStringEncoding)) } NSStringAPIs.test("capitalizedString") { expectEqual("Foo Foo Foo Foo", "foo Foo fOO FOO".capitalizedString) expectEqual("Жжж", "жжж".capitalizedString) } NSStringAPIs.test("capitalizedStringWithLocale(_:)") { expectEqual("Foo Foo Foo Foo", "foo Foo fOO FOO".capitalizedStringWithLocale(NSLocale.currentLocale())) expectEqual("Жжж", "жжж".capitalizedStringWithLocale(NSLocale.currentLocale())) expectEqual("Foo Foo Foo Foo", "foo Foo fOO FOO".capitalizedStringWithLocale(nil)) expectEqual("Жжж", "жжж".capitalizedStringWithLocale(nil)) } 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("commonPrefixWithString(_:options:)") { expectEqual("ab", "abcd".commonPrefixWithString("abdc", options: NSStringCompareOptions(0))) expectEqual("abC", "abCd".commonPrefixWithString("abce", options: .CaseInsensitiveSearch)) expectEqual("аб", "абвг".commonPrefixWithString("абгв", options: NSStringCompareOptions(0))) expectEqual("абВ", "абВг".commonPrefixWithString("абвд", 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)) if true { 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 ] expectTrue(equal(expectedBytes, bytes)) } } 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, inout stop: Bool) in lines.append(line) if lines.count == 3 { stop = true } } expectEqual([ "abc", "", "defghi" ], lines) } NSStringAPIs.test("enumerateLinguisticTagsInRange(_:scheme:options:orthography:_:") { let s = "Абв. Глокая куздра штеко будланула бокра и кудрячит бокрёнка. Абв." let startIndex = advance(s.startIndex, 5) let endIndex = advance(s.startIndex, 62) var tags: [String] = [] var tokens: [String] = [] var sentences: [String] = [] s.enumerateLinguisticTagsInRange(startIndex.., sentenceRange: Range, inout stop: 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, inout stop: Bool) in substrings.append(substring) expectEqual(substring, s[substringRange]) expectEqual(substring, s[enclosingRange]) } expectEqual([ "\u{304b}\u{3099}", "お", "☺️", "😀" ], substrings) } NSStringAPIs.test("fastestEncoding") { let availableEncodings: [NSStringEncoding] = String.availableStringEncodings() expectTrue(contains(availableEncodings, "abc".fastestEncoding)) } NSStringAPIs.test("fileSystemRepresentation()") { if true { let expectedStr = map("abc\0".utf8) { Int8(bitPattern: $0) } expectEqual(expectedStr, "abc".fileSystemRepresentation()) } // On OSX file system representation is Unicode NFD. // This test might need to be adjusted for other systems. if true { let expectedStr = map("\u{305f}\u{3099}くてん\0".utf8) { Int8(bitPattern: $0) } expectEqual(expectedStr, "だくてん".fileSystemRepresentation()) } } NSStringAPIs.test("getBytes(_:maxLength:usedLength:encoding:options:range:remainingRange:)") { let s = "abc абв def где gh жз zzz" let startIndex = advance(s.startIndex, 8) let endIndex = advance(s.startIndex, 22) if true { // 'maxLength' is limiting. let bufferLength = 100 var expectedStr: [UInt8] = Array("def где ".utf8) while (expectedStr.count != bufferLength) { expectedStr.append(0xff) } var buffer = [UInt8](count: bufferLength, repeatedValue: 0xff) var usedLength = 0 var remainingRange = startIndex..] = [] var tags = s.linguisticTagsInRange(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("rangeOfCharacterFromSet(_:options:range:)") { if true { let charset = NSCharacterSet(charactersInString: "абв") if true { let s = "Глокая куздра" let r = s.rangeOfCharacterFromSet(charset)! expectEqual(advance(s.startIndex, 4), r.startIndex) expectEqual(advance(s.startIndex, 5), r.endIndex) } if true { expectEmpty("клмн".rangeOfCharacterFromSet(charset)) } if true { let s = "абвклмнабвклмн" let r = s.rangeOfCharacterFromSet(charset, options: .BackwardsSearch)! expectEqual(advance(s.startIndex, 9), r.startIndex) expectEqual(advance(s.startIndex, 10), r.endIndex) } if true { let s = "абвклмнабв" let r = s.rangeOfCharacterFromSet(charset, range: advance(s.startIndex, 3).. String { #if os(OSX) return String.fromCString(getpwuid(getuid()).memory.pw_dir)! #elseif os(iOS) // getpwuid() returns null in sandboxed apps under iOS simulator. return NSHomeDirectory() #else preconditionFailed("implement") #endif } NSStringAPIs.test("stringByAbbreviatingWithTildeInPath") { let s = getHomeDir() + "/abcde.txt" expectEqual("~/abcde.txt", s.stringByAbbreviatingWithTildeInPath) } NSStringAPIs.test("stringByAddingPercentEncodingWithAllowedCharacters(_:)") { expectOptionalEqual("ab%63d %D0%B0%D0%B1%D0%B2%D0%B3", "abcd абвг".stringByAddingPercentEncodingWithAllowedCharacters( NSCharacterSet(charactersInString: "abd "))) } NSStringAPIs.test("stringByAddingPercentEscapesUsingEncoding(_:)") { expectEmpty( "abcd абвг".stringByAddingPercentEscapesUsingEncoding( NSASCIIStringEncoding)) expectOptionalEqual("abcd%20%D0%B0%D0%B1%D0%B2%D0%B3", "abcd абвг".stringByAddingPercentEscapesUsingEncoding( NSUTF8StringEncoding)) } NSStringAPIs.test("stringByAppendingFormat(_:_:...)") { expectEqual("", "".stringByAppendingFormat("")) expectEqual("a", "a".stringByAppendingFormat("")) expectEqual( "abc абв \u{0001F60A}", "abc абв \u{0001F60A}".stringByAppendingFormat("")) let formatArg: NSString = "привет мир \u{0001F60A}" expectEqual( "abc абв \u{0001F60A}def привет мир \u{0001F60A} 42", "abc абв \u{0001F60A}" .stringByAppendingFormat("def %@ %ld", formatArg, 42)) } NSStringAPIs.test("stringByAppendingPathComponent(_:)") { expectEqual("", "".stringByAppendingPathComponent("")) expectEqual("a.txt", "".stringByAppendingPathComponent("a.txt")) expectEqual("/tmp/a.txt", "/tmp".stringByAppendingPathComponent("a.txt")) } NSStringAPIs.test("stringByAppendingPathExtension(_:)") { expectEmpty("".stringByAppendingPathExtension("")) expectOptionalEqual("a.txt.", "a.txt".stringByAppendingPathExtension("")) expectEmpty("".stringByAppendingPathExtension("txt")) expectOptionalEqual("a.txt", "a".stringByAppendingPathExtension("txt")) expectOptionalEqual("a.txt.old", "a.txt".stringByAppendingPathExtension("old")) expectOptionalEqual("/tmp/a.txt.old", "/tmp/a.txt".stringByAppendingPathExtension("old")) } NSStringAPIs.test("stringByAppendingString(_:)") { expectEqual("", "".stringByAppendingString("")) expectEqual("a", "a".stringByAppendingString("")) expectEqual("a", "".stringByAppendingString("a")) expectEqual("さ\u{3099}", "さ".stringByAppendingString("\u{3099}")) } NSStringAPIs.test("stringByDeletingLastPathComponent") { expectEqual("", "".stringByDeletingLastPathComponent) expectEqual("/", "/".stringByDeletingLastPathComponent) expectEqual("/", "/tmp".stringByDeletingLastPathComponent) expectEqual("/tmp", "/tmp/a.txt".stringByDeletingLastPathComponent) } NSStringAPIs.test("stringByDeletingPathExtension") { expectEqual("", "".stringByDeletingPathExtension) expectEqual("/", "/".stringByDeletingPathExtension) expectEqual("/tmp", "/tmp".stringByDeletingPathExtension) expectEqual("/tmp/a", "/tmp/a.txt".stringByDeletingPathExtension) expectEqual("/tmp/a.txt", "/tmp/a.txt.old".stringByDeletingPathExtension) } NSStringAPIs.test("stringByExpandingTildeInPath") { let s = getHomeDir() + "/abcde.txt" expectEqual(s, "~/abcde.txt".stringByExpandingTildeInPath) } NSStringAPIs.test("stringByFoldingWithOptions(_:locale:)") { expectEqual("abcd", "abCD".stringByFoldingWithOptions( .CaseInsensitiveSearch, locale: NSLocale(localeIdentifier: "en"))) // U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE // to lower case: // U+0069 LATIN SMALL LETTER I // U+0307 COMBINING DOT ABOVE expectEqual("\u{0069}\u{0307}", "\u{0130}".stringByFoldingWithOptions( .CaseInsensitiveSearch, locale: NSLocale(localeIdentifier: "en"))) // U+0130 LATIN CAPITAL LETTER I WITH DOT ABOVE // to lower case in Turkish locale: // U+0069 LATIN SMALL LETTER I expectEqual("\u{0069}", "\u{0130}".stringByFoldingWithOptions( .CaseInsensitiveSearch, locale: NSLocale(localeIdentifier: "tr"))) expectEqual( "example123", "example123".stringByFoldingWithOptions( .WidthInsensitiveSearch, locale: NSLocale(localeIdentifier: "en"))) } NSStringAPIs.test("stringByPaddingToLength(_:withString:startingAtIndex:)") { expectEqual( "abc абв \u{0001F60A}", "abc абв \u{0001F60A}".stringByPaddingToLength( 10, withString: "XYZ", startingAtIndex: 0)) expectEqual( "abc абв \u{0001F60A}XYZXY", "abc абв \u{0001F60A}".stringByPaddingToLength( 15, withString: "XYZ", startingAtIndex: 0)) expectEqual( "abc абв \u{0001F60A}YZXYZ", "abc абв \u{0001F60A}".stringByPaddingToLength( 15, withString: "XYZ", startingAtIndex: 1)) } NSStringAPIs.testXFail( "stringByRemovingPercentEncoding/OSX 10.9", xfail: [.OSXMinor(10, 9, reason: "looks like a bug in Foundation in OS X 10.9")] ) { expectOptionalEqual("", "".stringByRemovingPercentEncoding) } NSStringAPIs.test("stringByRemovingPercentEncoding") { expectEmpty("%".stringByRemovingPercentEncoding) expectOptionalEqual( "abcd абвг", "ab%63d %D0%B0%D0%B1%D0%B2%D0%B3".stringByRemovingPercentEncoding) } NSStringAPIs.test("stringByReplacingCharactersInRange(_:withString:)") { // FIXME } NSStringAPIs.test("stringByReplacingOccurrencesOfString(_:withString:options:range:)") { // FIXME } NSStringAPIs.test("stringByReplacingPercentEscapesUsingEncoding(_:)") { // FIXME } NSStringAPIs.test("stringByResolvingSymlinksInPath") { // FIXME } NSStringAPIs.test("stringByStandardizingPath") { // FIXME } NSStringAPIs.test("stringByTrimmingCharactersInSet(_:)") { // FIXME } NSStringAPIs.test("stringsByAppendingPaths(_:)") { expectEqual([], "".stringsByAppendingPaths([])) expectEqual( [ "/tmp/foo", "/tmp/bar" ], "/tmp".stringsByAppendingPaths([ "foo", "bar" ])) } NSStringAPIs.test("substringFromIndex(_:)") { let s = "\u{1F601}abc さ\u{3099}し\u{3099}す\u{3099}せ\u{3099}そ\u{3099}" expectEqual(s, s.substringFromIndex(s.startIndex)) expectEqual("せ\u{3099}そ\u{3099}", s.substringFromIndex(advance(s.startIndex, 8))) expectEqual("", s.substringFromIndex(advance(s.startIndex, 10))) } NSStringAPIs.test("substringToIndex(_:)") { let s = "\u{1F601}abc さ\u{3099}し\u{3099}す\u{3099}せ\u{3099}そ\u{3099}" expectEqual("", s.substringToIndex(s.startIndex)) expectEqual("\u{1F601}abc さ\u{3099}し\u{3099}す\u{3099}", s.substringToIndex(advance(s.startIndex, 8))) expectEqual(s, s.substringToIndex(advance(s.startIndex, 10))) } NSStringAPIs.test("substringWithRange(_:)") { let s = "\u{1F601}abc さ\u{3099}し\u{3099}す\u{3099}せ\u{3099}そ\u{3099}" expectEqual("", s.substringWithRange(s.startIndex..= rhs, stackTrace: stackTrace) expectEqual(expected.isGT(), lhs > rhs, stackTrace: stackTrace) checkComparable(expected, lhs, rhs, stackTrace.withCurrentLoc()) // NSString / NSString let lhsNSString = lhs as NSString let rhsNSString = rhs as NSString let expectedEqualUnicodeScalars = Array(lhs.unicodeScalars) == Array(rhs.unicodeScalars) expectEqual( expectedEqualUnicodeScalars, lhsNSString == rhsNSString, stackTrace: stackTrace) expectEqual( !expectedEqualUnicodeScalars, lhsNSString != rhsNSString, stackTrace: stackTrace) checkHashable( expectedEqualUnicodeScalars, lhsNSString, rhsNSString, stackTrace.withCurrentLoc()) // Test mixed comparisons. // String / NSString expectEqual(expected.isEQ(), lhs == rhsNSString, stackTrace: stackTrace) expectEqual(expected.isNE(), lhs != rhsNSString, stackTrace: stackTrace) expectEqual(expected.isLT(), lhs < rhsNSString, stackTrace: stackTrace) expectEqual(expected.isLE(), lhs <= rhsNSString, stackTrace: stackTrace) expectEqual(expected.isGE(), lhs >= rhsNSString, stackTrace: stackTrace) expectEqual(expected.isGT(), lhs > rhsNSString, stackTrace: stackTrace) // NSString / String expectEqual(expected.isEQ(), lhsNSString == rhs, stackTrace: stackTrace) expectEqual(expected.isNE(), lhsNSString != rhs, stackTrace: stackTrace) expectEqual(expected.isLT(), lhsNSString < rhs, stackTrace: stackTrace) expectEqual(expected.isLE(), lhsNSString <= rhs, stackTrace: stackTrace) expectEqual(expected.isGE(), lhsNSString >= rhs, stackTrace: stackTrace) expectEqual(expected.isGT(), lhsNSString > rhs, stackTrace: stackTrace) } NSStringAPIs.test("String.{Equatable,Hashable,Comparable}") { for test in comparisonTests { checkStringComparison( test.expectedUnicodeCollation, test.lhs, test.rhs, test.loc.withCurrentLoc()) checkStringComparison( test.expectedUnicodeCollation.flip(), test.rhs, test.lhs, test.loc.withCurrentLoc()) } } func checkCharacterComparison( expected: ExpectedComparisonResult, lhs: Character, rhs: Character, stackTrace: SourceLocStack ) { // Character / Character expectEqual(expected.isEQ(), lhs == rhs, stackTrace: stackTrace) expectEqual(expected.isNE(), lhs != rhs, stackTrace: stackTrace) checkHashable(expected.isEQ(), lhs, rhs, stackTrace.withCurrentLoc()) expectEqual(expected.isLT(), lhs < rhs, stackTrace: stackTrace) expectEqual(expected.isLE(), lhs <= rhs, stackTrace: stackTrace) expectEqual(expected.isGE(), lhs >= rhs, stackTrace: stackTrace) expectEqual(expected.isGT(), lhs > rhs, stackTrace: stackTrace) checkComparable(expected, lhs, rhs, stackTrace.withCurrentLoc()) } NSStringAPIs.test("Character.{Equatable,Hashable,Comparable}") { for test in comparisonTests { if countElements(test.lhs) == 1 && countElements(test.rhs) == 1 { let lhsCharacter = Character(test.lhs) let rhsCharacter = Character(test.rhs) checkCharacterComparison( test.expectedUnicodeCollation, lhsCharacter, rhsCharacter, test.loc.withCurrentLoc()) checkCharacterComparison( test.expectedUnicodeCollation.flip(), rhsCharacter, lhsCharacter, test.loc.withCurrentLoc()) } } } func checkHasPrefixHasSuffix( lhs: String, rhs: String, stackTrace: SourceLocStack ) { if lhs == "" { return } if rhs == "" { expectFalse(lhs.hasPrefix(rhs), stackTrace: stackTrace) expectFalse(lhs.hasSuffix(rhs), stackTrace: stackTrace) return } // To determine the expected results, compare grapheme clusters, // scalar-to-scalar, of the NFD form of the strings. let lhsNFDGraphemeClusters = map(lhs.decomposedStringWithCanonicalMapping) { Array(String($0).unicodeScalars) } let rhsNFDGraphemeClusters = map(rhs.decomposedStringWithCanonicalMapping) { Array(String($0).unicodeScalars) } let expectHasPrefix = startsWith(lhsNFDGraphemeClusters, rhsNFDGraphemeClusters) { $0 == $1 } let expectHasSuffix = startsWith( lazy(lhsNFDGraphemeClusters).reverse(), lazy(rhsNFDGraphemeClusters).reverse()) { $0 == $1 } expectEqual(expectHasPrefix, lhs.hasPrefix(rhs), stackTrace: stackTrace) expectEqual( expectHasPrefix, (lhs + "abc").hasPrefix(rhs), stackTrace: stackTrace) expectEqual(expectHasSuffix, lhs.hasSuffix(rhs), stackTrace: stackTrace) expectEqual( expectHasSuffix, ("abc" + lhs).hasSuffix(rhs), stackTrace: stackTrace) } NSStringAPIs.test("hasPrefix,hasSuffix") { for test in comparisonTests { checkHasPrefixHasSuffix(test.lhs, test.rhs, test.loc.withCurrentLoc()) checkHasPrefixHasSuffix(test.rhs, test.lhs, test.loc.withCurrentLoc()) } } // FIXME: these properties should be implemented in the core library. // [unicode] Implement case folding NSStringAPIs.test("lowercaseString") { expectEqual("abcd", "abCD".lowercaseString) expectEqual("абвг", "абВГ".lowercaseString) expectEqual("たちつてと", "たちつてと".lowercaseString) // // 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 expectEqual("\u{0069}\u{0307}", "\u{0130}".lowercaseString) // 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 expectEqual("\u{0069}\u{0307}", "\u{0049}\u{0307}".lowercaseString) } NSStringAPIs.test("uppercaseString") { expectEqual("ABCD", "abCD".uppercaseString) expectEqual("АБВГ", "абВГ".uppercaseString) expectEqual("たちつてと", "たちつてと".uppercaseString) // // Special casing. // // U+0069 LATIN SMALL LETTER I // to upper case: // U+0049 LATIN CAPITAL LETTER I expectEqual("\u{0049}", "\u{0069}".uppercaseString) // 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. expectEqual("\u{0053}\u{0053}", "\u{00df}".uppercaseString) // 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. expectEqual("\u{0046}\u{0049}", "\u{fb01}".uppercaseString) } NSStringAPIs.run() // CHECK: NSStringAPIs: All tests passed var CStringTests = TestCase("CStringTests") func getNullCString() -> UnsafeMutablePointer { return .null() } func getASCIICString() -> (UnsafeMutablePointer, dealloc: ()->()) { var up = UnsafeMutablePointer.alloc(100) up[0] = 0x61 up[1] = 0x62 up[2] = 0 return (up, { up.dealloc(100) }) } func getNonASCIICString() -> (UnsafeMutablePointer, dealloc: ()->()) { var up = UnsafeMutablePointer.alloc(100) up[0] = 0xd0 up[1] = 0xb0 up[2] = 0xd0 up[3] = 0xb1 up[4] = 0 return (UnsafeMutablePointer(up), { up.dealloc(100) }) } func getIllFormedUTF8String1() -> (UnsafeMutablePointer, dealloc: ()->()) { var up = UnsafeMutablePointer.alloc(100) up[0] = 0x41 up[1] = 0xed up[2] = 0xa0 up[3] = 0x80 up[4] = 0x41 up[5] = 0 return (UnsafeMutablePointer(up), { up.dealloc(100) }) } func getIllFormedUTF8String2() -> (UnsafeMutablePointer, dealloc: ()->()) { var up = UnsafeMutablePointer.alloc(100) up[0] = 0x41 up[1] = 0xed up[2] = 0xa0 up[3] = 0x81 up[4] = 0x41 up[5] = 0 return (UnsafeMutablePointer(up), { up.dealloc(100) }) } func asCCharArray(a: [UInt8]) -> [CChar] { return a.map { CChar(bitPattern: $0) } } CStringTests.test("String.fromCString") { if true { let s = getNullCString() expectEmpty(String.fromCString(s)) } if true { let (s, dealloc) = getASCIICString() expectOptionalEqual("ab", String.fromCString(s)) dealloc() } if true { let (s, dealloc) = getNonASCIICString() expectOptionalEqual("аб", String.fromCString(s)) dealloc() } if true { let (s, dealloc) = getIllFormedUTF8String1() expectEmpty(String.fromCString(s)) dealloc() } } CStringTests.test("String.fromCStringRepairingIllFormedUTF8") { if true { let s = getNullCString() let (result, hadError) = String.fromCStringRepairingIllFormedUTF8(s) expectEmpty(result) expectFalse(hadError) } if true { let (s, dealloc) = getASCIICString() let (result, hadError) = String.fromCStringRepairingIllFormedUTF8(s) expectOptionalEqual("ab", result) expectFalse(hadError) dealloc() } if true { let (s, dealloc) = getNonASCIICString() let (result, hadError) = String.fromCStringRepairingIllFormedUTF8(s) expectOptionalEqual("аб", result) expectFalse(hadError) dealloc() } if true { let (s, dealloc) = getIllFormedUTF8String1() let (result, hadError) = String.fromCStringRepairingIllFormedUTF8(s) expectOptionalEqual("\u{41}\u{fffd}\u{fffd}\u{fffd}\u{41}", result) expectTrue(hadError) dealloc() } } CStringTests.run() // CHECK: {{^}}CStringTests: All tests passed