stdlib: Fix hasPrefix,hasSuffix tests

Comparing unicodeScalars like this is not valid.

Swift SVN r31477
This commit is contained in:
Arnold Schwaighofer
2015-08-26 03:57:25 +00:00
parent 2588f44d83
commit 3cc2dae6e6

View File

@@ -1842,16 +1842,22 @@ NSStringAPIs.test("stringByApplyingTransform(_:reverse:)") {
struct ComparisonTest {
let expectedUnicodeCollation: ExpectedComparisonResult
let expectedHasPrefix: Bool
let expectedHasSuffix: Bool
let lhs: String
let rhs: String
let loc: SourceLoc
init(
hasPrefix: Bool,
hasSuffix: Bool,
_ expectedUnicodeCollation: ExpectedComparisonResult,
_ lhs: String, _ rhs: String,
file: String = __FILE__, line: UInt = __LINE__
) {
self.expectedUnicodeCollation = expectedUnicodeCollation
self.expectedHasPrefix = hasPrefix
self.expectedHasSuffix = hasSuffix
self.lhs = lhs
self.rhs = rhs
self.loc = SourceLoc(file, line, comment: "test data")
@@ -1859,23 +1865,23 @@ struct ComparisonTest {
}
let comparisonTests = [
ComparisonTest(.EQ, "", ""),
ComparisonTest(.LT, "", "a"),
ComparisonTest(hasPrefix: false, hasSuffix: false, .EQ, "", ""),
ComparisonTest(hasPrefix: false, hasSuffix: false, .LT, "", "a"),
// 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.
// 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
// ordering relation.
ComparisonTest(.EQ, "\u{0}", ""),
ComparisonTest(.EQ, "\u{1}", "\u{0}"),
ComparisonTest(.LT, "\r\n", "t"),
// Currently fails:
//ComparisonTest(.GT, "\r\n", "\n"),
ComparisonTest(.EQ, "\u{0}", "\u{0}\u{0}"),
ComparisonTest(hasPrefix: false, hasSuffix: false, .EQ, "\u{0}", ""),
ComparisonTest(hasPrefix: false, hasSuffix: false, .EQ, "\u{1}", "\u{0}"),
ComparisonTest(hasPrefix: false, hasSuffix: false, .LT, "\r\n", "t"),
ComparisonTest(hasPrefix: false, hasSuffix: true, .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}"),
// Whitespace
// U+000A LINE FEED (LF)
@@ -1884,57 +1890,58 @@ let comparisonTests = [
// U+0085 NEXT LINE (NEL)
// U+2028 LINE SEPARATOR
// U+2029 PARAGRAPH SEPARATOR
ComparisonTest(.GT, "\u{0085}", "\n"),
ComparisonTest(.GT, "\u{000b}", "\n"),
ComparisonTest(.GT, "\u{000c}", "\n"),
ComparisonTest(.GT, "\u{2028}", "\n"),
ComparisonTest(.GT, "\u{2029}", "\n"),
ComparisonTest(.GT, "\r\n\r\n", "\r\n"),
ComparisonTest(hasPrefix: false, hasSuffix: false, .GT, "\u{0085}", "\n"),
ComparisonTest(hasPrefix: false, hasSuffix: false, .GT, "\u{000b}", "\n"),
ComparisonTest(hasPrefix: false, hasSuffix: false, .GT, "\u{000c}", "\n"),
ComparisonTest(hasPrefix: false, hasSuffix: false, .GT, "\u{2028}", "\n"),
ComparisonTest(hasPrefix: false, hasSuffix: false, .GT, "\u{2029}", "\n"),
ComparisonTest(hasPrefix: true, hasSuffix: true, .GT, "\r\n\r\n", "\r\n"),
// U+0301 COMBINING ACUTE ACCENT
// U+00E1 LATIN SMALL LETTER A WITH ACUTE
ComparisonTest(.EQ, "a\u{301}", "\u{e1}"),
ComparisonTest(.LT, "a", "a\u{301}"),
ComparisonTest(.LT, "a", "\u{e1}"),
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "a\u{301}", "\u{e1}"),
ComparisonTest(hasPrefix: false, hasSuffix: false, .LT, "a", "a\u{301}"),
ComparisonTest(hasPrefix: false, hasSuffix: false, .LT, "a", "\u{e1}"),
// U+304B HIRAGANA LETTER KA
// U+304C HIRAGANA LETTER GA
// U+3099 COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK
ComparisonTest(.EQ, "\u{304b}", "\u{304b}"),
ComparisonTest(.EQ, "\u{304c}", "\u{304c}"),
ComparisonTest(.LT, "\u{304b}", "\u{304c}"),
ComparisonTest(.LT, "\u{304b}", "\u{304c}\u{3099}"),
ComparisonTest(.EQ, "\u{304c}", "\u{304b}\u{3099}"),
ComparisonTest(.LT, "\u{304c}", "\u{304c}\u{3099}"),
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "\u{304b}", "\u{304b}"),
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "\u{304c}", "\u{304c}"),
ComparisonTest(hasPrefix: false, hasSuffix: false, .LT, "\u{304b}", "\u{304c}"),
ComparisonTest(hasPrefix: false, hasSuffix: false, .LT, "\u{304b}", "\u{304c}\u{3099}"),
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "\u{304c}", "\u{304b}\u{3099}"),
ComparisonTest(hasPrefix: false, hasSuffix: false, .LT, "\u{304c}", "\u{304c}\u{3099}"),
// U+212B ANGSTROM SIGN
// U+030A COMBINING RING ABOVE
// U+00C5 LATIN CAPITAL LETTER A WITH RING ABOVE
ComparisonTest(.EQ, "\u{212b}", "A\u{30a}"),
ComparisonTest(.EQ, "\u{212b}", "\u{c5}"),
ComparisonTest(.EQ, "A\u{30a}", "\u{c5}"),
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "\u{212b}", "A\u{30a}"),
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "\u{212b}", "\u{c5}"),
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "A\u{30a}", "\u{c5}"),
ComparisonTest(.GT, "A\u{30a}", "a"),
ComparisonTest(.LT, "A", "A\u{30a}"),
ComparisonTest(hasPrefix: false, hasSuffix: false, .GT, "A\u{30a}", "a"),
ComparisonTest(hasPrefix: false, hasSuffix: false, .LT, "A", "A\u{30a}"),
// U+2126 OHM SIGN
// 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+0307 COMBINING DOT ABOVE
// U+1E63 LATIN SMALL LETTER S WITH DOT BELOW
// U+1E69 LATIN SMALL LETTER S WITH DOT BELOW AND DOT ABOVE
ComparisonTest(.EQ, "\u{1e69}", "s\u{323}\u{307}"),
ComparisonTest(.EQ, "\u{1e69}", "s\u{307}\u{323}"),
ComparisonTest(.EQ, "\u{1e69}", "\u{1e63}\u{307}"),
ComparisonTest(.EQ, "\u{1e63}", "s\u{323}"),
ComparisonTest(.EQ, "\u{1e63}\u{307}", "s\u{323}\u{307}"),
ComparisonTest(.EQ, "\u{1e63}\u{307}", "s\u{307}\u{323}"),
ComparisonTest(.LT, "s\u{323}", "\u{1e69}"),
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "\u{1e69}", "s\u{323}\u{307}"),
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "\u{1e69}", "s\u{307}\u{323}"),
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "\u{1e69}", "\u{1e63}\u{307}"),
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "\u{1e63}", "s\u{323}"),
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "\u{1e63}\u{307}", "s\u{323}\u{307}"),
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "\u{1e63}\u{307}", "s\u{307}\u{323}"),
ComparisonTest(hasPrefix: false, hasSuffix: false, .LT, "s\u{323}", "\u{1e69}"),
// U+FB01 LATIN SMALL LIGATURE FI
ComparisonTest(.EQ, "\u{fb01}", "\u{fb01}"),
ComparisonTest(.LT, "fi", "\u{fb01}"),
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "\u{fb01}", "\u{fb01}"),
ComparisonTest(hasPrefix: false, hasSuffix: false, .LT, "fi", "\u{fb01}"),
// 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+0341 has a canonical decomposition mapping of U+0301.
ComparisonTest(.EQ, "\u{0301}", "\u{0341}"),
ComparisonTest(.EQ, "\u{0301}", "\u{0954}"),
ComparisonTest(.EQ, "\u{0341}", "\u{0954}"),
ComparisonTest(hasPrefix: true, hasSuffix: true, .EQ, "\u{0301}", "\u{0341}"),
ComparisonTest(hasPrefix: false, hasSuffix: false, .EQ, "\u{0301}", "\u{0954}"),
ComparisonTest(hasPrefix: false, hasSuffix: false, .EQ, "\u{0341}", "\u{0954}"),
]
func forceUTF16String(var str: String) -> String {
@@ -2068,7 +2075,8 @@ NSStringAPIs.test("Character.{Equatable,Hashable,Comparable}") {
}
func checkHasPrefixHasSuffix(
lhs: String, _ rhs: String, _ stackTrace: SourceLocStack
expectedHasPrefix: Bool, _ expectedHasSuffix: Bool, _ lhs: String,
_ rhs: String, _ stackTrace: SourceLocStack
) {
if lhs == "" {
return
@@ -2079,49 +2087,18 @@ func checkHasPrefixHasSuffix(
return
}
// To determine the expected results, compare grapheme clusters,
// 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(expectedHasPrefix, lhs.hasPrefix(rhs), stackTrace: stackTrace)
expectEqual(
expectHasPrefix, (lhs + "abc").hasPrefix(rhs), stackTrace: stackTrace)
expectEqual(expectHasSuffix, lhs.hasSuffix(rhs), stackTrace: stackTrace)
expectedHasPrefix, (lhs + "abc").hasPrefix(rhs), stackTrace: stackTrace)
expectEqual(expectedHasSuffix, lhs.hasSuffix(rhs), stackTrace: stackTrace)
expectEqual(
expectHasSuffix, ("abc" + lhs).hasSuffix(rhs), stackTrace: stackTrace)
expectedHasSuffix, ("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())
}
}
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())
checkHasPrefixHasSuffix(test.expectedHasPrefix, test.expectedHasSuffix,
test.lhs, test.rhs, test.loc.withCurrentLoc())
}
}