mirror of
https://github.com/apple/swift.git
synced 2025-12-21 12:14:44 +01:00
stdlib: Fix hasPrefix,hasSuffix tests
Comparing unicodeScalars like this is not valid. Swift SVN r31477
This commit is contained in:
@@ -1842,16 +1842,22 @@ NSStringAPIs.test("stringByApplyingTransform(_:reverse:)") {
|
|||||||
|
|
||||||
struct ComparisonTest {
|
struct ComparisonTest {
|
||||||
let expectedUnicodeCollation: ExpectedComparisonResult
|
let expectedUnicodeCollation: ExpectedComparisonResult
|
||||||
|
let expectedHasPrefix: Bool
|
||||||
|
let expectedHasSuffix: Bool
|
||||||
let lhs: String
|
let lhs: String
|
||||||
let rhs: String
|
let rhs: String
|
||||||
let loc: SourceLoc
|
let loc: SourceLoc
|
||||||
|
|
||||||
init(
|
init(
|
||||||
|
hasPrefix: Bool,
|
||||||
|
hasSuffix: Bool,
|
||||||
_ expectedUnicodeCollation: ExpectedComparisonResult,
|
_ expectedUnicodeCollation: ExpectedComparisonResult,
|
||||||
_ lhs: String, _ rhs: String,
|
_ lhs: String, _ rhs: String,
|
||||||
file: String = __FILE__, line: UInt = __LINE__
|
file: String = __FILE__, line: UInt = __LINE__
|
||||||
) {
|
) {
|
||||||
self.expectedUnicodeCollation = expectedUnicodeCollation
|
self.expectedUnicodeCollation = expectedUnicodeCollation
|
||||||
|
self.expectedHasPrefix = hasPrefix
|
||||||
|
self.expectedHasSuffix = hasSuffix
|
||||||
self.lhs = lhs
|
self.lhs = lhs
|
||||||
self.rhs = rhs
|
self.rhs = rhs
|
||||||
self.loc = SourceLoc(file, line, comment: "test data")
|
self.loc = SourceLoc(file, line, comment: "test data")
|
||||||
@@ -1859,23 +1865,23 @@ struct ComparisonTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let comparisonTests = [
|
let comparisonTests = [
|
||||||
ComparisonTest(.EQ, "", ""),
|
ComparisonTest(hasPrefix: false, hasSuffix: false, .EQ, "", ""),
|
||||||
ComparisonTest(.LT, "", "a"),
|
ComparisonTest(hasPrefix: false, hasSuffix: false, .LT, "", "a"),
|
||||||
|
|
||||||
// ASCII cases
|
// ASCII cases
|
||||||
ComparisonTest(.LT, "t", "tt"),
|
ComparisonTest(hasPrefix: false, hasSuffix: false, .LT, "t", "tt"),
|
||||||
|
ComparisonTest(hasPrefix: true, hasSuffix: true, .GT, "tt", "t"),
|
||||||
// According to DUCET: a < A < b < B.
|
// According to DUCET: a < A < b < B.
|
||||||
// This is NOT ascii order.
|
// This is NOT ascii order.
|
||||||
ComparisonTest(.GT, "T", "t"),
|
ComparisonTest(hasPrefix: false, hasSuffix: false, .GT, "T", "t"),
|
||||||
// According to DUCET \0 has no collation value and so is ignored in the
|
// According to DUCET \0 has no collation value and so is ignored in the
|
||||||
// ordering relation.
|
// ordering relation.
|
||||||
ComparisonTest(.EQ, "\u{0}", ""),
|
ComparisonTest(hasPrefix: false, hasSuffix: false, .EQ, "\u{0}", ""),
|
||||||
ComparisonTest(.EQ, "\u{1}", "\u{0}"),
|
ComparisonTest(hasPrefix: false, hasSuffix: false, .EQ, "\u{1}", "\u{0}"),
|
||||||
ComparisonTest(.LT, "\r\n", "t"),
|
ComparisonTest(hasPrefix: false, hasSuffix: false, .LT, "\r\n", "t"),
|
||||||
// Currently fails:
|
ComparisonTest(hasPrefix: false, hasSuffix: true, .GT, "\r\n", "\n"),
|
||||||
//ComparisonTest(.GT, "\r\n", "\n"),
|
ComparisonTest(hasPrefix: false, hasSuffix: false, .EQ, "\u{0}", "\u{0}\u{0}"),
|
||||||
|
ComparisonTest(hasPrefix: false, hasSuffix: true, .EQ, "\u{0}\u{0}", "\u{0}"),
|
||||||
ComparisonTest(.EQ, "\u{0}", "\u{0}\u{0}"),
|
|
||||||
|
|
||||||
// Whitespace
|
// Whitespace
|
||||||
// U+000A LINE FEED (LF)
|
// U+000A LINE FEED (LF)
|
||||||
@@ -1884,57 +1890,58 @@ let comparisonTests = [
|
|||||||
// U+0085 NEXT LINE (NEL)
|
// U+0085 NEXT LINE (NEL)
|
||||||
// U+2028 LINE SEPARATOR
|
// U+2028 LINE SEPARATOR
|
||||||
// U+2029 PARAGRAPH SEPARATOR
|
// U+2029 PARAGRAPH SEPARATOR
|
||||||
ComparisonTest(.GT, "\u{0085}", "\n"),
|
ComparisonTest(hasPrefix: false, hasSuffix: false, .GT, "\u{0085}", "\n"),
|
||||||
ComparisonTest(.GT, "\u{000b}", "\n"),
|
ComparisonTest(hasPrefix: false, hasSuffix: false, .GT, "\u{000b}", "\n"),
|
||||||
ComparisonTest(.GT, "\u{000c}", "\n"),
|
ComparisonTest(hasPrefix: false, hasSuffix: false, .GT, "\u{000c}", "\n"),
|
||||||
ComparisonTest(.GT, "\u{2028}", "\n"),
|
ComparisonTest(hasPrefix: false, hasSuffix: false, .GT, "\u{2028}", "\n"),
|
||||||
ComparisonTest(.GT, "\u{2029}", "\n"),
|
ComparisonTest(hasPrefix: false, hasSuffix: false, .GT, "\u{2029}", "\n"),
|
||||||
ComparisonTest(.GT, "\r\n\r\n", "\r\n"),
|
ComparisonTest(hasPrefix: true, hasSuffix: true, .GT, "\r\n\r\n", "\r\n"),
|
||||||
|
|
||||||
// U+0301 COMBINING ACUTE ACCENT
|
// U+0301 COMBINING ACUTE ACCENT
|
||||||
// U+00E1 LATIN SMALL LETTER A WITH ACUTE
|
// U+00E1 LATIN SMALL LETTER A WITH ACUTE
|
||||||
ComparisonTest(.EQ, "a\u{301}", "\u{e1}"),
|
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "a\u{301}", "\u{e1}"),
|
||||||
ComparisonTest(.LT, "a", "a\u{301}"),
|
ComparisonTest(hasPrefix: false, hasSuffix: false, .LT, "a", "a\u{301}"),
|
||||||
ComparisonTest(.LT, "a", "\u{e1}"),
|
ComparisonTest(hasPrefix: false, hasSuffix: false, .LT, "a", "\u{e1}"),
|
||||||
|
|
||||||
// U+304B HIRAGANA LETTER KA
|
// U+304B HIRAGANA LETTER KA
|
||||||
// U+304C HIRAGANA LETTER GA
|
// U+304C HIRAGANA LETTER GA
|
||||||
// U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
|
// U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
|
||||||
ComparisonTest(.EQ, "\u{304b}", "\u{304b}"),
|
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "\u{304b}", "\u{304b}"),
|
||||||
ComparisonTest(.EQ, "\u{304c}", "\u{304c}"),
|
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "\u{304c}", "\u{304c}"),
|
||||||
ComparisonTest(.LT, "\u{304b}", "\u{304c}"),
|
ComparisonTest(hasPrefix: false, hasSuffix: false, .LT, "\u{304b}", "\u{304c}"),
|
||||||
ComparisonTest(.LT, "\u{304b}", "\u{304c}\u{3099}"),
|
ComparisonTest(hasPrefix: false, hasSuffix: false, .LT, "\u{304b}", "\u{304c}\u{3099}"),
|
||||||
ComparisonTest(.EQ, "\u{304c}", "\u{304b}\u{3099}"),
|
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "\u{304c}", "\u{304b}\u{3099}"),
|
||||||
ComparisonTest(.LT, "\u{304c}", "\u{304c}\u{3099}"),
|
ComparisonTest(hasPrefix: false, hasSuffix: false, .LT, "\u{304c}", "\u{304c}\u{3099}"),
|
||||||
|
|
||||||
// U+212B ANGSTROM SIGN
|
// U+212B ANGSTROM SIGN
|
||||||
// U+030A COMBINING RING ABOVE
|
// U+030A COMBINING RING ABOVE
|
||||||
// U+00C5 LATIN CAPITAL LETTER A WITH RING ABOVE
|
// U+00C5 LATIN CAPITAL LETTER A WITH RING ABOVE
|
||||||
ComparisonTest(.EQ, "\u{212b}", "A\u{30a}"),
|
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "\u{212b}", "A\u{30a}"),
|
||||||
ComparisonTest(.EQ, "\u{212b}", "\u{c5}"),
|
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "\u{212b}", "\u{c5}"),
|
||||||
ComparisonTest(.EQ, "A\u{30a}", "\u{c5}"),
|
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "A\u{30a}", "\u{c5}"),
|
||||||
|
|
||||||
ComparisonTest(.GT, "A\u{30a}", "a"),
|
ComparisonTest(hasPrefix: false, hasSuffix: false, .GT, "A\u{30a}", "a"),
|
||||||
ComparisonTest(.LT, "A", "A\u{30a}"),
|
ComparisonTest(hasPrefix: false, hasSuffix: false, .LT, "A", "A\u{30a}"),
|
||||||
|
|
||||||
// U+2126 OHM SIGN
|
// U+2126 OHM SIGN
|
||||||
// U+03A9 GREEK CAPITAL LETTER OMEGA
|
// U+03A9 GREEK CAPITAL LETTER OMEGA
|
||||||
ComparisonTest(.EQ, "\u{2126}", "\u{03a9}"),
|
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "\u{2126}", "\u{03a9}"),
|
||||||
|
|
||||||
// U+0323 COMBINING DOT BELOW
|
// U+0323 COMBINING DOT BELOW
|
||||||
// U+0307 COMBINING DOT ABOVE
|
// U+0307 COMBINING DOT ABOVE
|
||||||
// U+1E63 LATIN SMALL LETTER S WITH DOT BELOW
|
// U+1E63 LATIN SMALL LETTER S WITH DOT BELOW
|
||||||
// U+1E69 LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE
|
// U+1E69 LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE
|
||||||
ComparisonTest(.EQ, "\u{1e69}", "s\u{323}\u{307}"),
|
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "\u{1e69}", "s\u{323}\u{307}"),
|
||||||
ComparisonTest(.EQ, "\u{1e69}", "s\u{307}\u{323}"),
|
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "\u{1e69}", "s\u{307}\u{323}"),
|
||||||
ComparisonTest(.EQ, "\u{1e69}", "\u{1e63}\u{307}"),
|
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "\u{1e69}", "\u{1e63}\u{307}"),
|
||||||
ComparisonTest(.EQ, "\u{1e63}", "s\u{323}"),
|
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "\u{1e63}", "s\u{323}"),
|
||||||
ComparisonTest(.EQ, "\u{1e63}\u{307}", "s\u{323}\u{307}"),
|
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "\u{1e63}\u{307}", "s\u{323}\u{307}"),
|
||||||
ComparisonTest(.EQ, "\u{1e63}\u{307}", "s\u{307}\u{323}"),
|
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "\u{1e63}\u{307}", "s\u{307}\u{323}"),
|
||||||
ComparisonTest(.LT, "s\u{323}", "\u{1e69}"),
|
ComparisonTest(hasPrefix: false, hasSuffix: false, .LT, "s\u{323}", "\u{1e69}"),
|
||||||
|
|
||||||
// U+FB01 LATIN SMALL LIGATURE FI
|
// U+FB01 LATIN SMALL LIGATURE FI
|
||||||
ComparisonTest(.EQ, "\u{fb01}", "\u{fb01}"),
|
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "\u{fb01}", "\u{fb01}"),
|
||||||
ComparisonTest(.LT, "fi", "\u{fb01}"),
|
ComparisonTest(hasPrefix: false, hasSuffix: false, .LT, "fi", "\u{fb01}"),
|
||||||
|
|
||||||
// We don't perform Unicode collation in semi-stable mode.
|
// We don't perform Unicode collation in semi-stable mode.
|
||||||
//
|
//
|
||||||
@@ -1949,9 +1956,9 @@ let comparisonTests = [
|
|||||||
//
|
//
|
||||||
// U+0301 and U+0954 don't decompose in the canonical decomposition mapping.
|
// U+0301 and U+0954 don't decompose in the canonical decomposition mapping.
|
||||||
// U+0341 has a canonical decomposition mapping of U+0301.
|
// U+0341 has a canonical decomposition mapping of U+0301.
|
||||||
ComparisonTest(.EQ, "\u{0301}", "\u{0341}"),
|
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "\u{0301}", "\u{0341}"),
|
||||||
ComparisonTest(.EQ, "\u{0301}", "\u{0954}"),
|
ComparisonTest(hasPrefix: false, hasSuffix: false, .EQ, "\u{0301}", "\u{0954}"),
|
||||||
ComparisonTest(.EQ, "\u{0341}", "\u{0954}"),
|
ComparisonTest(hasPrefix: false, hasSuffix: false, .EQ, "\u{0341}", "\u{0954}"),
|
||||||
]
|
]
|
||||||
|
|
||||||
func forceUTF16String(var str: String) -> String {
|
func forceUTF16String(var str: String) -> String {
|
||||||
@@ -2068,7 +2075,8 @@ NSStringAPIs.test("Character.{Equatable,Hashable,Comparable}") {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func checkHasPrefixHasSuffix(
|
func checkHasPrefixHasSuffix(
|
||||||
lhs: String, _ rhs: String, _ stackTrace: SourceLocStack
|
expectedHasPrefix: Bool, _ expectedHasSuffix: Bool, _ lhs: String,
|
||||||
|
_ rhs: String, _ stackTrace: SourceLocStack
|
||||||
) {
|
) {
|
||||||
if lhs == "" {
|
if lhs == "" {
|
||||||
return
|
return
|
||||||
@@ -2079,49 +2087,18 @@ func checkHasPrefixHasSuffix(
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// To determine the expected results, compare grapheme clusters,
|
expectEqual(expectedHasPrefix, lhs.hasPrefix(rhs), stackTrace: stackTrace)
|
||||||
// scalar-to-scalar, of the NFD form of the strings.
|
|
||||||
let lhsNFDGraphemeClusters =
|
|
||||||
lhs.decomposedStringWithCanonicalMapping.characters.map {
|
|
||||||
Array(String($0).unicodeScalars)
|
|
||||||
}
|
|
||||||
let rhsNFDGraphemeClusters =
|
|
||||||
rhs.decomposedStringWithCanonicalMapping.characters.map {
|
|
||||||
Array(String($0).unicodeScalars)
|
|
||||||
}
|
|
||||||
let expectHasPrefix = lhsNFDGraphemeClusters.startsWith(
|
|
||||||
rhsNFDGraphemeClusters, isEquivalent: (==))
|
|
||||||
let expectHasSuffix =
|
|
||||||
lhsNFDGraphemeClusters.lazy.reverse().startsWith(
|
|
||||||
rhsNFDGraphemeClusters.lazy.reverse(), isEquivalent: (==))
|
|
||||||
|
|
||||||
expectEqual(expectHasPrefix, lhs.hasPrefix(rhs), stackTrace: stackTrace)
|
|
||||||
expectEqual(
|
expectEqual(
|
||||||
expectHasPrefix, (lhs + "abc").hasPrefix(rhs), stackTrace: stackTrace)
|
expectedHasPrefix, (lhs + "abc").hasPrefix(rhs), stackTrace: stackTrace)
|
||||||
expectEqual(expectHasSuffix, lhs.hasSuffix(rhs), stackTrace: stackTrace)
|
expectEqual(expectedHasSuffix, lhs.hasSuffix(rhs), stackTrace: stackTrace)
|
||||||
expectEqual(
|
expectEqual(
|
||||||
expectHasSuffix, ("abc" + lhs).hasSuffix(rhs), stackTrace: stackTrace)
|
expectedHasSuffix, ("abc" + lhs).hasSuffix(rhs), stackTrace: stackTrace)
|
||||||
}
|
}
|
||||||
|
|
||||||
NSStringAPIs.test("hasPrefix,hasSuffix") {
|
NSStringAPIs.test("hasPrefix,hasSuffix") {
|
||||||
for test in comparisonTests {
|
for test in comparisonTests {
|
||||||
checkHasPrefixHasSuffix(test.lhs, test.rhs, test.loc.withCurrentLoc())
|
checkHasPrefixHasSuffix(test.expectedHasPrefix, test.expectedHasSuffix,
|
||||||
checkHasPrefixHasSuffix(test.rhs, test.lhs, test.loc.withCurrentLoc())
|
test.lhs, test.rhs, test.loc.withCurrentLoc())
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NSStringAPIs.test("Failures{hasPrefix,hasSuffix}-CF") {
|
|
||||||
//.xfail(.Custom({ true }, reason: "rdar://problem/19034601")).code {
|
|
||||||
let test = ComparisonTest(.LT, "\u{0}", "\u{0}\u{0}")
|
|
||||||
checkHasPrefixHasSuffix(test.lhs, test.rhs, test.loc.withCurrentLoc())
|
|
||||||
}
|
|
||||||
|
|
||||||
NSStringAPIs.test("Failures{hasPrefix,hasSuffix}")
|
|
||||||
.xfail(.Custom({ true }, reason: "blocked on rdar://problem/19036555")).code {
|
|
||||||
let tests =
|
|
||||||
[ComparisonTest(.LT, "\r\n", "t"), ComparisonTest(.GT, "\r\n", "\n")]
|
|
||||||
tests.forEach {
|
|
||||||
checkHasPrefixHasSuffix($0.lhs, $0.rhs, $0.loc.withCurrentLoc())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user